ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/src/conf.C
Revision: 1.4
Committed: Tue Aug 28 17:08:12 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.3: +491 -418 lines
Log Message:
- changed name
- updated the example config to the new system
- added more documentation
- enhanced documentation generators
- added a link to the pdf to the website
- added an RSS feed generator
- transitioned hooks to c++ callbacks
- did various merges with upstream along the way
- added const where appropriate
- removed the old block allocator
- fixed most memory leaks
- transitioned some dictionaries to std::map
- transitioned some lists to std::vector
- made some free functions members where appropriate
- renamed string to dynstr and added a static string ststr
- use NOW instead of time (NULL) if possible
- completely reworked database backends, crypto handlers and protocol handlers
  to use an object factory
- removed the old module system. ermyth does not do any dynamic loading anymore
- fixed most of the build system
- reworked how protocol commands work

File Contents

# Content
1 /*
2 * conf.C: Configuration processing.
3 * Rights to this code are documented in doc/pod/license.pod.
4 *
5 * Copyright © 2005-2007 Atheme Project (http://www.atheme.org)
6 */
7
8 static char const rcsid[] = "$Id: conf.C,v 1.3 2007-07-21 13:23:21 pippijn Exp $";
9
10 #include "atheme.h"
11 #include <ermyth/crypto.h>
12 #include <ermyth/database.h>
13 #include <ermyth/module.h>
14 #include <account/myuser.h>
15 #include <account/mychan.h>
16 #include <account/chanacs.h>
17 #include "uplink.h"
18 #include "pmodule.h"
19 #include "privs.h"
20
21 ConfTable::callbacks ConfTable::callback;
22
23 #define PARAM_ERROR(ce) \
24 { \
25 slog(LG_INFO, "%s:%i: no parameter for " \
26 "configuration option: %s", \
27 (ce)->ce_fileptr->cf_filename, \
28 (ce)->ce_varlinenum, (ce)->ce_varname); \
29 return 1; \
30 }
31
32 static int c_serverinfo (config_entry_t *);
33 static int c_general (config_entry_t *);
34 static int c_database (config_entry_t *);
35 static int c_uplink (config_entry_t *);
36 static int c_chanserv (config_entry_t *);
37 static int c_globserv (config_entry_t *);
38 static int c_operserv (config_entry_t *);
39 static int c_memoserv (config_entry_t *);
40 static int c_gameserv (config_entry_t *);
41 static int c_nickserv (config_entry_t *);
42 static int c_saslserv (config_entry_t *);
43 static int c_loadmodule (config_entry_t *);
44 static int c_backend (config_entry_t *);
45 static int c_crypto (config_entry_t *);
46 static int c_protocol (config_entry_t *);
47 static int c_operclass (config_entry_t *);
48 static int c_operator (config_entry_t *);
49 static int c_logfile (config_entry_t *);
50
51 static int c_si_name (config_entry_t *);
52 static int c_si_desc (config_entry_t *);
53 static int c_si_numeric (config_entry_t *);
54 static int c_si_vhost (config_entry_t *);
55 static int c_si_recontime (config_entry_t *);
56 static int c_si_restarttime (config_entry_t *);
57 static int c_si_netname (config_entry_t *);
58 static int c_si_hidehostsuffix (config_entry_t *);
59 static int c_si_adminname (config_entry_t *);
60 static int c_si_adminemail (config_entry_t *);
61 static int c_si_mta (config_entry_t *);
62 static int c_si_loglevel (config_entry_t *);
63 static int c_si_maxlogins (config_entry_t *);
64 static int c_si_maxusers (config_entry_t *);
65 static int c_si_maxnicks (config_entry_t *);
66 static int c_si_maxchans (config_entry_t *);
67 static int c_si_emaillimit (config_entry_t *);
68 static int c_si_emailtime (config_entry_t *);
69 static int c_si_auth (config_entry_t *);
70 static int c_si_mdlimit (config_entry_t *);
71 static int c_si_casemapping (config_entry_t *);
72
73 /* ChanServ client information. */
74 static int c_ci_nick (config_entry_t *);
75 static int c_ci_user (config_entry_t *);
76 static int c_ci_host (config_entry_t *);
77 static int c_ci_real (config_entry_t *);
78 static int c_ci_fantasy (config_entry_t *);
79 static int c_ci_vop (config_entry_t *);
80 static int c_ci_hop (config_entry_t *);
81 static int c_ci_aop (config_entry_t *);
82 static int c_ci_sop (config_entry_t *);
83 static int c_ci_changets (config_entry_t *);
84 static int c_ci_trigger (config_entry_t *);
85 static int c_ci_expire (config_entry_t *);
86 static int c_ci_maxchanacs (config_entry_t *);
87 static int c_ci_maxfounders (config_entry_t *);
88
89 /* GlobServ client information. */
90 static int c_gl_nick (config_entry_t *);
91 static int c_gl_user (config_entry_t *);
92 static int c_gl_host (config_entry_t *);
93 static int c_gl_real (config_entry_t *);
94
95 /* OperServ client information. */
96 static int c_oi_nick (config_entry_t *);
97 static int c_oi_user (config_entry_t *);
98 static int c_oi_host (config_entry_t *);
99 static int c_oi_real (config_entry_t *);
100
101 /* NickServ client information. */
102 static int c_ni_nick (config_entry_t *);
103 static int c_ni_user (config_entry_t *);
104 static int c_ni_host (config_entry_t *);
105 static int c_ni_real (config_entry_t *);
106 static int c_ni_spam (config_entry_t *);
107 static int c_ni_no_nick_ownership (config_entry_t *);
108 static int c_ni_expire (config_entry_t *);
109
110 /* SaslServ client information. */
111 static int c_ss_nick (config_entry_t *);
112 static int c_ss_user (config_entry_t *);
113 static int c_ss_host (config_entry_t *);
114 static int c_ss_real (config_entry_t *);
115
116 /* MemoServ client information. */
117 static int c_ms_nick (config_entry_t *);
118 static int c_ms_user (config_entry_t *);
119 static int c_ms_host (config_entry_t *);
120 static int c_ms_real (config_entry_t *);
121
122 /* GameServ client information. */
123 static int c_gs_nick (config_entry_t *);
124 static int c_gs_user (config_entry_t *);
125 static int c_gs_host (config_entry_t *);
126 static int c_gs_real (config_entry_t *);
127
128 /* Database information. */
129 static int c_db_user (config_entry_t *);
130 static int c_db_host (config_entry_t *);
131 static int c_db_password (config_entry_t *);
132 static int c_db_database (config_entry_t *);
133 static int c_db_port (config_entry_t *);
134
135 static int c_gi_chan (config_entry_t *);
136 static int c_gi_silent (config_entry_t *);
137 static int c_gi_verbose_wallops (config_entry_t *);
138 static int c_gi_use_privmsg (config_entry_t *);
139 static int c_gi_join_chans (config_entry_t *);
140 static int c_gi_leave_chans (config_entry_t *);
141 static int c_gi_uflags (config_entry_t *);
142 static int c_gi_cflags (config_entry_t *);
143 static int c_gi_raw (config_entry_t *);
144 static int c_gi_flood_msgs (config_entry_t *);
145 static int c_gi_flood_time (config_entry_t *);
146 static int c_gi_kline_time (config_entry_t *);
147 static int c_gi_commit_interval (config_entry_t *);
148 static int c_gi_expire (config_entry_t *);
149 static int c_gi_secure (config_entry_t *);
150 static int c_gi_default_clone_limit (config_entry_t *);
151
152 /* *INDENT-OFF* */
153
154 static Token uflags[] = {
155 { "HOLD", MU_HOLD },
156 { "NEVEROP", MU_NEVEROP },
157 { "NOOP", MU_NOOP },
158 { "HIDEMAIL", MU_HIDEMAIL },
159 { "NONE", 0 },
160 { NULL, 0 }
161 };
162
163 static Token cflags[] = {
164 { "HOLD", MC_HOLD },
165 { "SECURE", MC_SECURE },
166 { "VERBOSE", MC_VERBOSE },
167 { "KEEPTOPIC", MC_KEEPTOPIC },
168 { "VERBOSE_OPS", MC_VERBOSE_OPS },
169 { "TOPICLOCK", MC_TOPICLOCK },
170 { "GUARD", MC_GUARD },
171 { "NONE", 0 },
172 { NULL, 0 }
173 };
174
175 static Token logflags[] = {
176 { "DEBUG", LG_ALL },
177 { "TRACE", LG_INFO | LG_ERROR | LG_CMD_ALL | LG_NETWORK | LG_WALLOPS | LG_REGISTER },
178 { "MISC", LG_INFO | LG_ERROR | LG_CMD_ADMIN | LG_CMD_REGISTER | LG_CMD_SET | LG_NETWORK | LG_WALLOPS | LG_REGISTER },
179 { "NOTICE", LG_INFO | LG_ERROR | LG_CMD_ADMIN | LG_CMD_REGISTER | LG_NETWORK | LG_REGISTER },
180 { "ALL", LG_ALL },
181 { "INFO", LG_INFO },
182 { "ERROR", LG_ERROR },
183 { "COMMANDS", LG_CMD_ALL },
184 { "ADMIN", LG_CMD_ADMIN },
185 { "REGISTER", LG_CMD_REGISTER | LG_REGISTER },
186 { "SET", LG_CMD_SET },
187 { "NETWORK", LG_NETWORK },
188 { "WALLOPS", LG_WALLOPS },
189 { "RAWDATA", LG_RAWDATA },
190 { NULL, 0 }
191 };
192
193 static list_t confblocks;
194 static list_t conf_si_table;
195 static list_t conf_ci_table;
196 static list_t conf_gl_table;
197 static list_t conf_oi_table;
198 static list_t conf_ni_table;
199 static list_t conf_db_table;
200 static list_t conf_gi_table;
201 static list_t conf_ms_table;
202 static list_t conf_la_table;
203 static list_t conf_ss_table;
204 static list_t conf_gs_table;
205
206 /* *INDENT-ON* */
207
208 static void
209 conf_report_error (config_entry_t *ce, char const * const fmt, ...)
210 {
211 va_list va;
212 char buf[BUFSIZE];
213
214 return_if_fail (ce != NULL);
215 return_if_fail (fmt != NULL);
216
217 va_start (va, fmt);
218 vsnprintf (buf, BUFSIZE, fmt, va);
219 va_end (va);
220
221 slog (LG_INFO, "%s:%d: configuration error - %s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, buf);
222 }
223
224 static void
225 conf_process (config_file_t *cfp)
226 {
227 config_file_t *cfptr;
228 config_entry_t *ce;
229 node_t *tn;
230 ConfTable *ct = NULL;
231
232 for (cfptr = cfp; cfptr; cfptr = cfptr->cf_next)
233 {
234 for (ce = cfptr->cf_entries; ce; ce = ce->ce_next)
235 {
236 LIST_FOREACH (tn, confblocks.head)
237 {
238 ct = static_cast<ConfTable *> (tn->data);
239
240 if (!strcasecmp (ct->name, ce->ce_varname))
241 {
242 ct->handler (ce);
243 break;
244 }
245 }
246
247 if (ct == NULL)
248 conf_report_error (ce, "invalid configuration option: %s", ce->ce_varname);
249 }
250 }
251 }
252
253 bool
254 conf_parse (char *file)
255 {
256 config_file_t *cfp;
257
258 cfp = config_load (file);
259 if (cfp == NULL)
260 {
261 slog (LG_ERROR, "conf_parse(): unable to load configuration file: %s", strerror (errno));
262
263 return false;
264 }
265
266 conf_process (cfp);
267 config_free (cfp);
268
269 if (!protocol::handler::loaded)
270 {
271 slog (LG_ERROR, "No protocol module loaded, aborting");
272 exit (EXIT_FAILURE);
273 }
274
275 ConfTable::callback.ready ();
276 return true;
277 }
278
279 void
280 conf_init (void)
281 {
282 me.init ();
283 if (chansvs.nick)
284 sfree (chansvs.nick);
285 if (config_options.chan)
286 sfree (config_options.chan);
287 if (config_options.global)
288 sfree (config_options.global);
289 if (config_options.languagefile)
290 sfree (config_options.languagefile);
291
292 chansvs.nick = config_options.chan = config_options.global = config_options.languagefile = NULL;
293
294 config_options.flood_msgs = config_options.flood_time = config_options.kline_time = config_options.commit_interval = 0;
295
296 nicksvs.expiry = chansvs.expiry = 0;
297
298 config_options.defuflags = config_options.defcflags = 0x00000000;
299
300 config_options.silent = config_options.join_chans = config_options.leave_chans = config_options.raw = false;
301
302 me.auth = AUTH_NONE;
303
304 me.mdlimit = 30;
305
306 chansvs.fantasy = false;
307 if (chansvs.me != NULL && fcmd_agent == chansvs.me)
308 fcmd_agent = NULL;
309 chansvs.ca_vop = CA_VOP_DEF & ca_all;
310 chansvs.ca_hop = CA_HOP_DEF & ca_all;
311 chansvs.ca_aop = CA_AOP_DEF & ca_all;
312 chansvs.ca_sop = CA_SOP_DEF & ca_all;
313 chansvs.changets = false;
314 if (chansvs.trigger != NULL)
315 sfree (chansvs.trigger);
316 chansvs.trigger = sstrdup ("!");
317 chansvs.maxchanacs = 0;
318 chansvs.maxfounders = 4;
319
320 if (!(runflags & RF_REHASHING))
321 {
322 if (me.name)
323 sfree (me.name);
324 if (me.desc)
325 sfree (me.desc);
326 if (me.vhost)
327 sfree (me.vhost);
328 if (chansvs.user)
329 sfree (chansvs.user);
330 if (chansvs.host)
331 sfree (chansvs.host);
332 if (chansvs.real)
333 sfree (chansvs.real);
334
335 me.name = me.desc = me.vhost = chansvs.user = chansvs.host = chansvs.real = NULL;
336
337 set_match_mapping (MATCH_RFC1459); /* default to RFC compliancy */
338 }
339 }
340
341 int
342 subblock_handler (config_entry_t *ce, list_t *entries)
343 {
344 node_t *tn;
345 ConfTable *ct = NULL;
346
347 for (ce = ce->ce_entries; ce; ce = ce->ce_next)
348 {
349 LIST_FOREACH (tn, entries->head)
350 {
351 ct = static_cast<ConfTable *> (tn->data);
352
353 if (!strcasecmp (ct->name, ce->ce_varname))
354 {
355 ct->handler (ce);
356 break;
357 }
358 }
359
360 if (ct == NULL)
361 conf_report_error (ce, "invalid configuration option: %s", ce->ce_varname);
362 }
363 return 0;
364 }
365
366 struct ConfTable *
367 find_top_conf (char const * const name)
368 {
369 node_t *n;
370 ConfTable *ct;
371
372 LIST_FOREACH (n, confblocks.head)
373 {
374 ct = static_cast<ConfTable *> (n->data);
375
376 if (!strcasecmp (ct->name, name))
377 return ct;
378 }
379
380 return NULL;
381 }
382
383 struct ConfTable *
384 find_conf_item (char const * const name, list_t *conflist)
385 {
386 node_t *n;
387 ConfTable *ct;
388
389 LIST_FOREACH (n, conflist->head)
390 {
391 ct = static_cast<ConfTable *> (n->data);
392
393 if (!strcasecmp (ct->name, name))
394 return ct;
395 }
396
397 return NULL;
398 }
399
400 void
401 add_top_conf (char const * const name, int (*handler) (config_entry_t *ce))
402 {
403 ConfTable *ct;
404
405 if ((ct = find_top_conf (name)))
406 {
407 slog (LG_DEBUG, "add_top_conf(): duplicate config block '%s'.", name);
408 return;
409 }
410
411 ct = new ConfTable (name, 1, handler);
412
413 node_add (ct, node_create (), &confblocks);
414 }
415
416 void
417 add_conf_item (char const * const name, list_t *conflist, int (*handler) (config_entry_t *ce))
418 {
419 ConfTable *ct;
420
421 if ((ct = find_conf_item (name, conflist)))
422 {
423 slog (LG_DEBUG, "add_conf_item(): duplicate item %s", name);
424 return;
425 }
426
427 ct = new ConfTable (name, 1, handler);
428
429 node_add (ct, node_create (), conflist);
430 }
431
432 void
433 del_top_conf (char const * const name)
434 {
435 node_t *n;
436 ConfTable *ct;
437
438 if (!(ct = find_top_conf (name)))
439 {
440 slog (LG_DEBUG, "del_top_conf(): cannot delete nonexistant block %s", name);
441 return;
442 }
443
444 n = node_find (ct, &confblocks);
445 node_del (n, &confblocks);
446
447 delete ct;
448 }
449
450 void
451 del_conf_item (char const * const name, list_t *conflist)
452 {
453 node_t *n;
454 ConfTable *ct;
455
456 if (!(ct = find_conf_item (name, conflist)))
457 {
458 slog (LG_DEBUG, "del_conf_item(): cannot delete nonexistant item %s", name);
459 return;
460 }
461
462 n = node_find (ct, conflist);
463 node_del (n, conflist);
464
465 delete ct;
466 }
467
468 /* stolen from Sentinel */
469 #define TOKEN_UNMATCHED -1
470 #define TOKEN_ERROR -2
471
472 static int
473 token_to_value (struct Token token_table[], char *token)
474 {
475 int i;
476
477 if ((token_table != NULL) && (token != NULL))
478 {
479 for (i = 0; token_table[i].text != NULL; i++)
480 {
481 if (strcasecmp (token_table[i].text, token) == 0)
482 {
483 return token_table[i].value;
484 }
485 }
486 /* If no match... */
487 return TOKEN_UNMATCHED;
488 }
489
490 /* Otherwise... */
491 return TOKEN_ERROR;
492 }
493
494 void
495 init_newconf (void)
496 {
497 #if 0
498 conftable_heap = BlockHeapCreate (sizeof (struct ConfTable), 32);
499 #endif
500
501 /* First we set up the blocks. */
502 add_top_conf ("SERVERINFO", c_serverinfo);
503 add_top_conf ("CHANSERV", c_chanserv);
504 add_top_conf ("GLOBAL", c_globserv);
505 add_top_conf ("OPERSERV", c_operserv);
506 add_top_conf ("NICKSERV", c_nickserv);
507 add_top_conf ("SASLSERV", c_saslserv);
508 add_top_conf ("MEMOSERV", c_memoserv);
509 add_top_conf ("GAMESERV", c_gameserv);
510 add_top_conf ("UPLINK", c_uplink);
511 add_top_conf ("GENERAL", c_general);
512 add_top_conf ("DATABASE", c_database);
513 add_top_conf ("LOADMODULE", c_loadmodule);
514 add_top_conf ("BACKEND", c_backend);
515 add_top_conf ("CRYPTO", c_crypto);
516 add_top_conf ("PROTOCOL", c_protocol);
517 add_top_conf ("OPERCLASS", c_operclass);
518 add_top_conf ("OPERATOR", c_operator);
519 add_top_conf ("LOGFILE", c_logfile);
520
521 /* Now we fill in the information */
522 add_conf_item ("NAME", &conf_si_table, c_si_name);
523 add_conf_item ("DESC", &conf_si_table, c_si_desc);
524 add_conf_item ("NUMERIC", &conf_si_table, c_si_numeric);
525 add_conf_item ("VHOST", &conf_si_table, c_si_vhost);
526 add_conf_item ("RECONTIME", &conf_si_table, c_si_recontime);
527 add_conf_item ("RESTARTTIME", &conf_si_table, c_si_restarttime);
528 add_conf_item ("EXPIRE", &conf_si_table, c_gi_expire);
529 add_conf_item ("NETNAME", &conf_si_table, c_si_netname);
530 add_conf_item ("HIDEHOSTSUFFIX", &conf_si_table, c_si_hidehostsuffix);
531 add_conf_item ("ADMINNAME", &conf_si_table, c_si_adminname);
532 add_conf_item ("ADMINEMAIL", &conf_si_table, c_si_adminemail);
533 add_conf_item ("MTA", &conf_si_table, c_si_mta);
534 add_conf_item ("LOGLEVEL", &conf_si_table, c_si_loglevel);
535 add_conf_item ("MAXLOGINS", &conf_si_table, c_si_maxlogins);
536 add_conf_item ("MAXUSERS", &conf_si_table, c_si_maxusers);
537 add_conf_item ("MAXNICKS", &conf_si_table, c_si_maxnicks);
538 add_conf_item ("MAXCHANS", &conf_si_table, c_si_maxchans);
539 add_conf_item ("EMAILLIMIT", &conf_si_table, c_si_emaillimit);
540 add_conf_item ("EMAILTIME", &conf_si_table, c_si_emailtime);
541 add_conf_item ("AUTH", &conf_si_table, c_si_auth);
542 add_conf_item ("MDLIMIT", &conf_si_table, c_si_mdlimit);
543 add_conf_item ("CASEMAPPING", &conf_si_table, c_si_casemapping);
544
545 /* general{} block. */
546 add_conf_item ("CHAN", &conf_gi_table, c_gi_chan);
547 add_conf_item ("VERBOSE_WALLOPS", &conf_gi_table, c_gi_verbose_wallops);
548 add_conf_item ("USE_PRIVMSG", &conf_gi_table, c_gi_use_privmsg);
549 add_conf_item ("SILENT", &conf_gi_table, c_gi_silent);
550 add_conf_item ("JOIN_CHANS", &conf_gi_table, c_gi_join_chans);
551 add_conf_item ("LEAVE_CHANS", &conf_gi_table, c_gi_leave_chans);
552 add_conf_item ("UFLAGS", &conf_gi_table, c_gi_uflags);
553 add_conf_item ("CFLAGS", &conf_gi_table, c_gi_cflags);
554 add_conf_item ("RAW", &conf_gi_table, c_gi_raw);
555 add_conf_item ("SECURE", &conf_gi_table, c_gi_secure);
556 add_conf_item ("FLOOD_MSGS", &conf_gi_table, c_gi_flood_msgs);
557 add_conf_item ("FLOOD_TIME", &conf_gi_table, c_gi_flood_time);
558 add_conf_item ("KLINE_TIME", &conf_gi_table, c_gi_kline_time);
559 add_conf_item ("COMMIT_INTERVAL", &conf_gi_table, c_gi_commit_interval);
560 add_conf_item ("EXPIRE", &conf_gi_table, c_gi_expire);
561 add_conf_item ("DEFAULT_CLONE_LIMIT", &conf_gi_table, c_gi_default_clone_limit);
562
563 /* chanserv{} block */
564 add_conf_item ("NICK", &conf_ci_table, c_ci_nick);
565 add_conf_item ("USER", &conf_ci_table, c_ci_user);
566 add_conf_item ("HOST", &conf_ci_table, c_ci_host);
567 add_conf_item ("REAL", &conf_ci_table, c_ci_real);
568 add_conf_item ("FANTASY", &conf_ci_table, c_ci_fantasy);
569 add_conf_item ("VOP", &conf_ci_table, c_ci_vop);
570 add_conf_item ("HOP", &conf_ci_table, c_ci_hop);
571 add_conf_item ("AOP", &conf_ci_table, c_ci_aop);
572 add_conf_item ("SOP", &conf_ci_table, c_ci_sop);
573 add_conf_item ("CHANGETS", &conf_ci_table, c_ci_changets);
574 add_conf_item ("TRIGGER", &conf_ci_table, c_ci_trigger);
575 add_conf_item ("EXPIRE", &conf_ci_table, c_ci_expire);
576 add_conf_item ("MAXCHANACS", &conf_ci_table, c_ci_maxchanacs);
577 add_conf_item ("MAXFOUNDERS", &conf_ci_table, c_ci_maxfounders);
578
579 /* global{} block */
580 add_conf_item ("NICK", &conf_gl_table, c_gl_nick);
581 add_conf_item ("USER", &conf_gl_table, c_gl_user);
582 add_conf_item ("HOST", &conf_gl_table, c_gl_host);
583 add_conf_item ("REAL", &conf_gl_table, c_gl_real);
584
585 /* operserv{} block */
586 add_conf_item ("NICK", &conf_oi_table, c_oi_nick);
587 add_conf_item ("USER", &conf_oi_table, c_oi_user);
588 add_conf_item ("HOST", &conf_oi_table, c_oi_host);
589 add_conf_item ("REAL", &conf_oi_table, c_oi_real);
590
591 /* nickserv{} block */
592 add_conf_item ("NICK", &conf_ni_table, c_ni_nick);
593 add_conf_item ("USER", &conf_ni_table, c_ni_user);
594 add_conf_item ("HOST", &conf_ni_table, c_ni_host);
595 add_conf_item ("REAL", &conf_ni_table, c_ni_real);
596 add_conf_item ("SPAM", &conf_ni_table, c_ni_spam);
597 add_conf_item ("NO_NICK_OWNERSHIP", &conf_ni_table, c_ni_no_nick_ownership);
598 add_conf_item ("EXPIRE", &conf_ni_table, c_ni_expire);
599
600 /* saslserv{} block */
601 add_conf_item ("NICK", &conf_ss_table, c_ss_nick);
602 add_conf_item ("USER", &conf_ss_table, c_ss_user);
603 add_conf_item ("HOST", &conf_ss_table, c_ss_host);
604 add_conf_item ("REAL", &conf_ss_table, c_ss_real);
605
606 /* memoserv{} block */
607 add_conf_item ("NICK", &conf_ms_table, c_ms_nick);
608 add_conf_item ("USER", &conf_ms_table, c_ms_user);
609 add_conf_item ("HOST", &conf_ms_table, c_ms_host);
610 add_conf_item ("REAL", &conf_ms_table, c_ms_real);
611
612 /* memoserv{} block */
613 add_conf_item ("NICK", &conf_gs_table, c_gs_nick);
614 add_conf_item ("USER", &conf_gs_table, c_gs_user);
615 add_conf_item ("HOST", &conf_gs_table, c_gs_host);
616 add_conf_item ("REAL", &conf_gs_table, c_gs_real);
617
618 /* database{} block */
619 add_conf_item ("USER", &conf_db_table, c_db_user);
620 add_conf_item ("HOST", &conf_db_table, c_db_host);
621 add_conf_item ("PASSWORD", &conf_db_table, c_db_password);
622 add_conf_item ("DATABASE", &conf_db_table, c_db_database);
623 add_conf_item ("PORT", &conf_db_table, c_db_port);
624 }
625
626 static int
627 c_serverinfo (config_entry_t *ce)
628 {
629 return subblock_handler (ce, &conf_si_table);
630 }
631
632 static int
633 c_chanserv (config_entry_t *ce)
634 {
635 return subblock_handler (ce, &conf_ci_table);
636 }
637
638 static int
639 c_globserv (config_entry_t *ce)
640 {
641 return subblock_handler (ce, &conf_gl_table);
642 }
643
644 static int
645 c_operserv (config_entry_t *ce)
646 {
647 return subblock_handler (ce, &conf_oi_table);
648 }
649
650 static int
651 c_nickserv (config_entry_t *ce)
652 {
653 return subblock_handler (ce, &conf_ni_table);
654 }
655
656 static int
657 c_saslserv (config_entry_t *ce)
658 {
659 return subblock_handler (ce, &conf_ss_table);
660 }
661
662 static int
663 c_memoserv (config_entry_t *ce)
664 {
665 return subblock_handler (ce, &conf_ms_table);
666 }
667
668 static int
669 c_gameserv (config_entry_t *ce)
670 {
671 return subblock_handler (ce, &conf_gs_table);
672 }
673
674 static int
675 c_database (config_entry_t *ce)
676 {
677 return subblock_handler (ce, &conf_db_table);
678 }
679
680 static int
681 c_protocol (config_entry_t *ce)
682 {
683 char *name;
684
685 if (cold_start == false)
686 return 0;
687
688 if (ce->ce_vardata == NULL)
689 PARAM_ERROR (ce);
690
691 name = ce->ce_vardata;
692
693 typedef factory::factory_mgr<protocol::handler> protocol_factory;
694 protocol_factory &f = protocol_factory::instance ();
695
696 if (!f.provides (name))
697 PARAM_ERROR (ce);
698
699 phandler = f.create (name);
700
701 return 0;
702 }
703
704 static int
705 c_loadmodule (config_entry_t *ce)
706 {
707 char *name;
708
709 if (cold_start == false)
710 return 0;
711
712 if (ce->ce_vardata == NULL)
713 PARAM_ERROR (ce);
714
715 name = ce->ce_vardata;
716
717 if (!modules::provides (name))
718 {
719 dbg << "No such module\n";
720 PARAM_ERROR (ce);
721 }
722
723 modules::enable (name);
724
725 return 0;
726 }
727
728 static int
729 c_crypto (config_entry_t *ce)
730 {
731 char *name;
732
733 if (cold_start == false)
734 return 0;
735
736 if (ce->ce_vardata == NULL)
737 PARAM_ERROR (ce);
738
739 name = ce->ce_vardata;
740
741 typedef factory::factory_mgr<crypto::handler> crypto_factory;
742 crypto_factory &f = crypto_factory::instance ();
743
744 if (!f.provides (name))
745 PARAM_ERROR (ce);
746
747 crypter = f.create (name);
748
749 return 0;
750 }
751
752 static int
753 c_backend (config_entry_t *ce)
754 {
755 char *name;
756
757 if (cold_start == false)
758 return 0;
759
760 if (ce->ce_vardata == NULL)
761 PARAM_ERROR (ce);
762
763 name = ce->ce_vardata;
764
765 typedef factory::factory_mgr<database::handler> backend_factory;
766 backend_factory &f = backend_factory::instance ();
767
768 if (!f.provides (name))
769 PARAM_ERROR (ce);
770
771 backend = f.create (name);
772
773 return 0;
774 }
775
776 static int
777 c_uplink (config_entry_t *ce)
778 {
779 char *name;
780 char *host = NULL, *vhost = NULL, *password = NULL;
781 unsigned int port = 0;
782
783 if (ce->ce_vardata == NULL)
784 PARAM_ERROR (ce);
785
786 if (me.name != NULL && !irccasecmp (ce->ce_vardata, me.name))
787 slog (LG_ERROR, "%s:%d: uplink's server name %s should not be the same as our server name, continuing anyway", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata);
788 else if (!strchr (ce->ce_vardata, '.'))
789 slog (LG_ERROR, "%s:%d: uplink's server name %s is invalid, continuing anyway", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata);
790 else if (isdigit (ce->ce_vardata[0]))
791 slog (LG_ERROR, "%s:%d: uplink's server name %s starts with a digit, probably invalid (continuing anyway)", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata);
792
793 name = sstrdup (ce->ce_vardata);
794
795 for (ce = ce->ce_entries; ce; ce = ce->ce_next)
796 {
797 if (!strcasecmp ("HOST", ce->ce_varname))
798 {
799 if (ce->ce_vardata == NULL)
800 PARAM_ERROR (ce);
801
802 host = sstrdup (ce->ce_vardata);
803 }
804 else if (!strcasecmp ("VHOST", ce->ce_varname))
805 {
806 if (ce->ce_vardata == NULL)
807 PARAM_ERROR (ce);
808
809 vhost = sstrdup (ce->ce_vardata);
810 }
811 else if (!strcasecmp ("PASSWORD", ce->ce_varname))
812 {
813 if (ce->ce_vardata == NULL)
814 PARAM_ERROR (ce);
815
816 password = sstrdup (ce->ce_vardata);
817 }
818 else if (!strcasecmp ("PORT", ce->ce_varname))
819 {
820 if (ce->ce_vardata == NULL)
821 PARAM_ERROR (ce);
822
823 port = ce->ce_vardatanum;
824 }
825 else
826 {
827 slog (LG_ERROR, "%s:%d: Invalid configuration option uplink::%s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_varname);
828 continue;
829 }
830 }
831
832 uplink_add (name, host, password, vhost, port);
833
834 sfree (name);
835 sfree (host);
836 sfree (password);
837 sfree (vhost);
838
839 return 0;
840 }
841
842 static int
843 c_operclass (config_entry_t *ce)
844 {
845 operclass_t *operclass;
846 char *name;
847 char *privs = NULL, *newprivs;
848 int flags = 0;
849
850 if (ce->ce_vardata == NULL)
851 PARAM_ERROR (ce);
852
853 name = ce->ce_vardata;
854
855 for (ce = ce->ce_entries; ce; ce = ce->ce_next)
856 {
857 if (!strcasecmp ("PRIVS", ce->ce_varname))
858 {
859 if (ce->ce_vardata == NULL && ce->ce_entries == NULL)
860 PARAM_ERROR (ce);
861
862 if (ce->ce_entries == NULL)
863 {
864 if (privs == NULL)
865 privs = sstrdup (ce->ce_vardata);
866 else
867 {
868 newprivs = alloc<char> (strlen (privs) + 1 + strlen (ce->ce_vardata) + 1);
869 strcpy (newprivs, privs);
870 strcat (newprivs, " ");
871 strcat (newprivs, ce->ce_vardata);
872 sfree (privs);
873 privs = newprivs;
874 }
875 }
876 else
877 {
878 config_entry_t *conf_p;
879 /*
880 * New definition format for operclasses.
881 *
882 * operclass "sra" {
883 * privs = {
884 * special:ircop;
885 * };
886 * };
887 *
888 * - nenolod
889 */
890 for (conf_p = ce->ce_entries; conf_p; conf_p = conf_p->ce_next)
891 {
892 if (privs == NULL)
893 privs = sstrdup (conf_p->ce_varname);
894 else
895 {
896 newprivs = alloc<char> (strlen (privs) + 1 + strlen (conf_p->ce_varname) + 1);
897 strcpy (newprivs, privs);
898 strcat (newprivs, " ");
899 strcat (newprivs, conf_p->ce_varname);
900 sfree (privs);
901 privs = newprivs;
902 }
903 }
904 }
905 }
906 else if (!strcasecmp ("NEEDOPER", ce->ce_varname))
907 flags |= OPERCLASS_NEEDOPER;
908 else
909 {
910 slog (LG_ERROR, "%s:%d: Invalid configuration option operclass::%s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_varname);
911 continue;
912 }
913 }
914
915 operclass = operclass_add (name, privs ? privs : "");
916 if (operclass != NULL)
917 operclass->flags |= flags;
918 sfree (privs);
919 return 0;
920 }
921
922 static int
923 c_operator (config_entry_t *ce)
924 {
925 char *name;
926 operclass_t *operclass = NULL;
927 config_entry_t *topce;
928
929 if (ce->ce_vardata == NULL)
930 PARAM_ERROR (ce);
931
932 topce = ce;
933 name = ce->ce_vardata;
934
935 for (ce = ce->ce_entries; ce; ce = ce->ce_next)
936 {
937 if (!strcasecmp ("OPERCLASS", ce->ce_varname))
938 {
939 if (ce->ce_vardata == NULL)
940 PARAM_ERROR (ce);
941
942 operclass = operclass_find (ce->ce_vardata);
943 if (operclass == NULL)
944 slog (LG_ERROR, "%s:%d: invalid operclass %s for operator %s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata, name);
945 }
946 else
947 {
948 slog (LG_ERROR, "%s:%d: Invalid configuration option operator::%s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_varname);
949 continue;
950 }
951 }
952
953 if (operclass != NULL)
954 soper_add (name, operclass->name, SOPER_CONF);
955 else
956 slog (LG_ERROR, "%s:%d: skipping operator %s because of bad/missing parameters", topce->ce_fileptr->cf_filename, topce->ce_varlinenum, name);
957 return 0;
958 }
959
960 static int
961 c_general (config_entry_t *ce)
962 {
963 return subblock_handler (ce, &conf_gi_table);
964 }
965
966 static int
967 c_si_name (config_entry_t *ce)
968 {
969 if (ce->ce_vardata == NULL)
970 PARAM_ERROR (ce);
971
972 if (!(runflags & RF_REHASHING))
973 me.name = sstrdup (ce->ce_vardata);
974
975 return 0;
976 }
977
978 static int
979 c_si_desc (config_entry_t *ce)
980 {
981 if (ce->ce_vardata == NULL)
982 PARAM_ERROR (ce);
983
984 if (me.desc != NULL)
985 sfree (me.desc);
986 me.desc = sstrdup (ce->ce_vardata);
987
988 return 0;
989 }
990
991 static int
992 c_si_numeric (config_entry_t *ce)
993 {
994 if (ce->ce_vardata == NULL)
995 PARAM_ERROR (ce);
996
997 if (!(runflags & RF_REHASHING))
998 me.numeric = sstrdup (ce->ce_vardata);
999
1000 return 0;
1001 }
1002
1003 static int
1004 c_si_mdlimit (config_entry_t *ce)
1005 {
1006 if (ce->ce_vardata == NULL)
1007 PARAM_ERROR (ce);
1008
1009 me.mdlimit = ce->ce_vardatanum;
1010
1011 return 0;
1012 }
1013
1014 static int
1015 c_si_vhost (config_entry_t *ce)
1016 {
1017 if (ce->ce_vardata == NULL)
1018 PARAM_ERROR (ce);
1019
1020 me.vhost = sstrdup (ce->ce_vardata);
1021
1022 return 0;
1023 }
1024
1025 static int
1026 c_si_recontime (config_entry_t *ce)
1027 {
1028 if (ce->ce_vardata == NULL)
1029 PARAM_ERROR (ce);
1030
1031 me.recontime = ce->ce_vardatanum;
1032
1033 return 0;
1034 }
1035
1036 static int
1037 c_si_restarttime (config_entry_t *ce)
1038 {
1039 if (ce->ce_vardata == NULL)
1040 PARAM_ERROR (ce);
1041
1042 me.restarttime = ce->ce_vardatanum;
1043
1044 return 0;
1045 }
1046
1047 static int
1048 c_si_netname (config_entry_t *ce)
1049 {
1050 if (ce->ce_vardata == NULL)
1051 PARAM_ERROR (ce);
1052
1053 me.netname = sstrdup (ce->ce_vardata);
1054
1055 return 0;
1056 }
1057
1058 static int
1059 c_si_hidehostsuffix (config_entry_t *ce)
1060 {
1061 if (ce->ce_vardata == NULL)
1062 PARAM_ERROR (ce);
1063
1064 me.hidehostsuffix = sstrdup (ce->ce_vardata);
1065
1066 return 0;
1067 }
1068
1069 static int
1070 c_si_adminname (config_entry_t *ce)
1071 {
1072 if (ce->ce_vardata == NULL)
1073 PARAM_ERROR (ce);
1074
1075 me.adminname = sstrdup (ce->ce_vardata);
1076
1077 return 0;
1078 }
1079
1080 static int
1081 c_si_adminemail (config_entry_t *ce)
1082 {
1083 if (ce->ce_vardata == NULL)
1084 PARAM_ERROR (ce);
1085
1086 me.adminemail = sstrdup (ce->ce_vardata);
1087
1088 return 0;
1089 }
1090
1091 static int
1092 c_si_mta (config_entry_t *ce)
1093 {
1094 if (ce->ce_vardata == NULL)
1095 PARAM_ERROR (ce);
1096
1097 me.mta = sstrdup (ce->ce_vardata);
1098
1099 return 0;
1100 }
1101
1102 static int
1103 c_si_loglevel (config_entry_t *ce)
1104 {
1105 config_entry_t *flce;
1106 int val;
1107 int mask = 0;
1108
1109 if (ce->ce_vardata != NULL)
1110 {
1111 val = token_to_value (logflags, ce->ce_vardata);
1112
1113 if ((val != TOKEN_UNMATCHED) && (val != TOKEN_ERROR))
1114 mask |= val;
1115 else
1116 {
1117 slog (LG_INFO, "%s:%d: unknown flag: %s", ce->ce_fileptr->cf_filename, ce->ce_varlinenum, ce->ce_vardata);
1118 }
1119 }
1120 for (flce = ce->ce_entries; flce; flce = flce->ce_next)
1121 {
1122 val = token_to_value (logflags, flce->ce_varname);
1123
1124 if ((val != TOKEN_UNMATCHED) && (val != TOKEN_ERROR))
1125 mask |= val;
1126 else
1127 {
1128 slog (LG_INFO, "%s:%d: unknown flag: %s", flce->ce_fileptr->cf_filename, flce->ce_varlinenum, flce->ce_varname);
1129 }
1130 }
1131 log_master_set_mask (mask);
1132
1133 return 0;
1134 }
1135
1136 static int
1137 c_si_maxlogins (config_entry_t *ce)
1138 {
1139 if (ce->ce_vardata == NULL)
1140 PARAM_ERROR (ce);
1141
1142 me.maxlogins = ce->ce_vardatanum;
1143
1144 return 0;
1145
1146 }
1147
1148 static int
1149 c_si_maxusers (config_entry_t *ce)
1150 {
1151 if (ce->ce_vardata == NULL)
1152 PARAM_ERROR (ce);
1153
1154 me.maxusers = ce->ce_vardatanum;
1155
1156 return 0;
1157
1158 }
1159
1160 static int
1161 c_si_maxnicks (config_entry_t *ce)
1162 {
1163 if (ce->ce_vardata == NULL)
1164 PARAM_ERROR (ce);
1165
1166 me.maxnicks = ce->ce_vardatanum;
1167
1168 return 0;
1169 }
1170
1171 static int
1172 c_si_maxchans (config_entry_t *ce)
1173 {
1174 if (ce->ce_vardata == NULL)
1175 PARAM_ERROR (ce);
1176
1177 me.maxchans = ce->ce_vardatanum;
1178
1179 return 0;
1180 }
1181
1182 static int
1183 c_si_emaillimit (config_entry_t *ce)
1184 {
1185 if (ce->ce_vardata == NULL)
1186 PARAM_ERROR (ce);
1187
1188 me.emaillimit = ce->ce_vardatanum;
1189
1190 return 0;
1191 }
1192
1193 static int
1194 c_si_emailtime (config_entry_t *ce)
1195 {
1196 if (ce->ce_vardata == NULL)
1197 PARAM_ERROR (ce);
1198
1199 me.emailtime = ce->ce_vardatanum;
1200
1201 return 0;
1202 }
1203
1204 static int
1205 c_si_auth (config_entry_t *ce)
1206 {
1207 if (ce->ce_vardata == NULL)
1208 PARAM_ERROR (ce);
1209
1210 if (!strcasecmp ("EMAIL", ce->ce_vardata))
1211 me.auth = AUTH_EMAIL;
1212
1213 else
1214 me.auth = AUTH_NONE;
1215
1216 return 0;
1217 }
1218
1219 static int
1220 c_si_casemapping (config_entry_t *ce)
1221 {
1222 if (ce->ce_vardata == NULL)
1223 PARAM_ERROR (ce);
1224
1225 if (!strcasecmp ("ASCII", ce->ce_vardata))
1226 set_match_mapping (MATCH_ASCII);
1227
1228 else
1229 set_match_mapping (MATCH_RFC1459);
1230
1231 return 0;
1232 }
1233
1234 static int
1235 c_ci_nick (config_entry_t *ce)
1236 {
1237 if (ce->ce_vardata == NULL)
1238 PARAM_ERROR (ce);
1239
1240 if (chansvs.nick != NULL)
1241 sfree (chansvs.nick);
1242 chansvs.nick = sstrdup (ce->ce_vardata);
1243
1244 return 0;
1245 }
1246
1247 static int
1248 c_ci_user (config_entry_t *ce)
1249 {
1250 if (ce->ce_vardata == NULL)
1251 PARAM_ERROR (ce);
1252
1253 if (chansvs.user != NULL)
1254 sfree (chansvs.user);
1255 chansvs.user = sstrdup (ce->ce_vardata);
1256
1257 return 0;
1258 }
1259
1260 static int
1261 c_ci_host (config_entry_t *ce)
1262 {
1263 if (ce->ce_vardata == NULL)
1264 PARAM_ERROR (ce);
1265
1266 if (chansvs.host != NULL)
1267 sfree (chansvs.host);
1268 chansvs.host = sstrdup (ce->ce_vardata);
1269
1270 return 0;
1271 }
1272
1273 static int
1274 c_ci_real (config_entry_t *ce)
1275 {
1276 if (ce->ce_vardata == NULL)
1277 PARAM_ERROR (ce);
1278
1279 if (chansvs.real != NULL)
1280 sfree (chansvs.real);
1281 chansvs.real = sstrdup (ce->ce_vardata);
1282
1283 return 0;
1284 }
1285
1286 static int
1287 c_ci_fantasy (config_entry_t *ce)
1288 {
1289 chansvs.fantasy = true;
1290
1291 if (chansvs.me != NULL)
1292 fcmd_agent = chansvs.me;
1293
1294 return 0;
1295 }
1296
1297 static int
1298 c_ci_vop (config_entry_t *ce)
1299 {
1300 if (ce->ce_vardata == NULL)
1301 PARAM_ERROR (ce);
1302
1303 chansvs.ca_vop = flags_to_bitmask (ce->ce_vardata, chanacs_flags, 0);
1304
1305 return 0;
1306 }
1307
1308 static int
1309 c_ci_hop (config_entry_t *ce)
1310 {
1311 if (ce->ce_vardata == NULL)
1312 PARAM_ERROR (ce);
1313
1314 chansvs.ca_hop = flags_to_bitmask (ce->ce_vardata, chanacs_flags, 0);
1315
1316 return 0;
1317 }
1318
1319 static int
1320 c_ci_aop (config_entry_t *ce)
1321 {
1322 if (ce->ce_vardata == NULL)
1323 PARAM_ERROR (ce);
1324
1325 chansvs.ca_aop = flags_to_bitmask (ce->ce_vardata, chanacs_flags, 0);
1326
1327 return 0;
1328 }
1329
1330 static int
1331 c_ci_sop (config_entry_t *ce)
1332 {
1333 if (ce->ce_vardata == NULL)
1334 PARAM_ERROR (ce);
1335
1336 chansvs.ca_sop = flags_to_bitmask (ce->ce_vardata, chanacs_flags, 0);
1337
1338 return 0;
1339 }
1340
1341 static int
1342 c_ci_changets (config_entry_t *ce)
1343 {
1344 chansvs.changets = true;
1345 return 0;
1346 }
1347
1348 static int
1349 c_ci_trigger (config_entry_t *ce)
1350 {
1351 if (ce->ce_vardata == NULL)
1352 PARAM_ERROR (ce);
1353
1354 if (chansvs.trigger != NULL)
1355 sfree (chansvs.trigger);
1356 chansvs.trigger = sstrdup (ce->ce_vardata);
1357
1358 return 0;
1359 }
1360
1361 static int
1362 c_ci_expire (config_entry_t *ce)
1363 {
1364 if (ce->ce_vardata == NULL)
1365 PARAM_ERROR (ce);
1366
1367 chansvs.expiry = (ce->ce_vardatanum * 60 * 60 * 24);
1368
1369 return 0;
1370 }
1371
1372 static int
1373 c_ci_maxchanacs (config_entry_t *ce)
1374 {
1375 if (ce->ce_vardata == NULL)
1376 PARAM_ERROR (ce);
1377
1378 chansvs.maxchanacs = ce->ce_vardatanum;
1379
1380 return 0;
1381 }
1382
1383 static int
1384 c_ci_maxfounders (config_entry_t *ce)
1385 {
1386 if (ce->ce_vardata == NULL)
1387 PARAM_ERROR (ce);
1388
1389 chansvs.maxfounders = ce->ce_vardatanum;
1390
1391 return 0;
1392 }
1393
1394 static int
1395 c_gi_chan (config_entry_t *ce)
1396 {
1397 if (ce->ce_vardata == NULL)
1398 PARAM_ERROR (ce);
1399
1400 config_options.chan = sstrdup (ce->ce_vardata);
1401
1402 return 0;
1403 }
1404
1405 static int
1406 c_gi_silent (config_entry_t *ce)
1407 {
1408 config_options.silent = true;
1409 return 0;
1410 }
1411
1412 static int
1413 c_gi_verbose_wallops (config_entry_t *ce)
1414 {
1415 config_options.verbose_wallops = true;
1416 return 0;
1417 }
1418
1419 static int
1420 c_gi_use_privmsg (config_entry_t *ce)
1421 {
1422 config_options.use_privmsg = true;
1423 return 0;
1424 }
1425
1426 static int
1427 c_gi_secure (config_entry_t *ce)
1428 {
1429 config_options.secure = true;
1430 return 0;
1431 }
1432
1433 static int
1434 c_gi_join_chans (config_entry_t *ce)
1435 {
1436 config_options.join_chans = true;
1437 return 0;
1438 }
1439
1440 static int
1441 c_gi_leave_chans (config_entry_t *ce)
1442 {
1443 config_options.leave_chans = true;
1444 return 0;
1445 }
1446
1447 static int
1448 c_gi_uflags (config_entry_t *ce)
1449 {
1450 config_entry_t *flce;
1451
1452 for (flce = ce->ce_entries; flce; flce = flce->ce_next)
1453 {
1454 int val;
1455
1456 val = token_to_value (uflags, flce->ce_varname);
1457
1458 if ((val != TOKEN_UNMATCHED) && (val != TOKEN_ERROR))
1459 config_options.defuflags |= val;
1460
1461 else
1462 {
1463 slog (LG_INFO, "%s:%d: unknown flag: %s", flce->ce_fileptr->cf_filename, flce->ce_varlinenum, flce->ce_varname);
1464 }
1465 }
1466
1467 return 0;
1468 }
1469
1470 static int
1471 c_gi_cflags (config_entry_t *ce)
1472 {
1473 config_entry_t *flce;
1474
1475 for (flce = ce->ce_entries; flce; flce = flce->ce_next)
1476 {
1477 int val;
1478
1479 val = token_to_value (cflags, flce->ce_varname);
1480
1481 if ((val != TOKEN_UNMATCHED) && (val != TOKEN_ERROR))
1482 config_options.defcflags |= val;
1483
1484 else
1485 {
1486 slog (LG_INFO, "%s:%d: unknown flag: %s", flce->ce_fileptr->cf_filename, flce->ce_varlinenum, flce->ce_varname);
1487 }
1488 }
1489
1490 if (config_options.defcflags & MC_TOPICLOCK)
1491 config_options.defcflags |= MC_KEEPTOPIC;
1492
1493 return 0;
1494 }
1495
1496 static int
1497 c_gi_raw (config_entry_t *ce)
1498 {
1499 config_options.raw = true;
1500 return 0;
1501 }
1502
1503 static int
1504 c_gi_flood_msgs (config_entry_t *ce)
1505 {
1506 if (ce->ce_vardata == NULL)
1507 PARAM_ERROR (ce);
1508
1509 config_options.flood_msgs = ce->ce_vardatanum;
1510
1511 return 0;
1512 }
1513
1514 static int
1515 c_gi_flood_time (config_entry_t *ce)
1516 {
1517 if (ce->ce_vardata == NULL)
1518 PARAM_ERROR (ce);
1519
1520 config_options.flood_time = ce->ce_vardatanum;
1521
1522 return 0;
1523 }
1524
1525 static int
1526 c_gi_kline_time (config_entry_t *ce)
1527 {
1528 if (ce->ce_vardata == NULL)
1529 PARAM_ERROR (ce);
1530
1531 config_options.kline_time = (ce->ce_vardatanum * 60 * 60 * 24);
1532
1533 return 0;
1534 }
1535
1536 static int
1537 c_gi_commit_interval (config_entry_t *ce)
1538 {
1539 if (ce->ce_vardata == NULL)
1540 PARAM_ERROR (ce);
1541
1542 config_options.commit_interval = (ce->ce_vardatanum * 60);
1543
1544 return 0;
1545 }
1546
1547 static int
1548 c_gi_expire (config_entry_t *ce)
1549 {
1550 if (ce->ce_vardata == NULL)
1551 PARAM_ERROR (ce);
1552
1553 slog (LG_INFO, "warning: general::expire has been deprecated. please use nickserv::expire and chanserv::expire respectively.");
1554
1555 nicksvs.expiry = (ce->ce_vardatanum * 60 * 60 * 24);
1556 chansvs.expiry = (ce->ce_vardatanum * 60 * 60 * 24);
1557
1558 return 0;
1559 }
1560
1561 static int
1562 c_gi_default_clone_limit (config_entry_t *ce)
1563 {
1564 if (ce->ce_vardata == NULL)
1565 PARAM_ERROR (ce);
1566
1567 config_options.default_clone_limit = ce->ce_vardatanum;
1568
1569 return 0;
1570 }
1571
1572 static int
1573 c_oi_nick (config_entry_t *ce)
1574 {
1575 if (ce->ce_vardata == NULL)
1576 PARAM_ERROR (ce);
1577
1578 if (opersvs.nick != NULL)
1579 sfree (opersvs.nick);
1580 opersvs.nick = sstrdup (ce->ce_vardata);
1581
1582 return 0;
1583 }
1584
1585 static int
1586 c_oi_user (config_entry_t *ce)
1587 {
1588 if (ce->ce_vardata == NULL)
1589 PARAM_ERROR (ce);
1590
1591 if (opersvs.user != NULL)
1592 sfree (opersvs.user);
1593 opersvs.user = sstrdup (ce->ce_vardata);
1594
1595 return 0;
1596 }
1597
1598 static int
1599 c_oi_host (config_entry_t *ce)
1600 {
1601 if (ce->ce_vardata == NULL)
1602 PARAM_ERROR (ce);
1603
1604 if (opersvs.host != NULL)
1605 sfree (opersvs.host);
1606 opersvs.host = sstrdup (ce->ce_vardata);
1607
1608 return 0;
1609 }
1610
1611 static int
1612 c_oi_real (config_entry_t *ce)
1613 {
1614 if (ce->ce_vardata == NULL)
1615 PARAM_ERROR (ce);
1616
1617 if (opersvs.real != NULL)
1618 sfree (opersvs.real);
1619 opersvs.real = sstrdup (ce->ce_vardata);
1620
1621 return 0;
1622 }
1623
1624 static int
1625 c_ni_nick (config_entry_t *ce)
1626 {
1627 if (ce->ce_vardata == NULL)
1628 PARAM_ERROR (ce);
1629
1630 if (nicksvs.nick != NULL)
1631 sfree (nicksvs.nick);
1632 nicksvs.nick = sstrdup (ce->ce_vardata);
1633
1634 return 0;
1635 }
1636
1637 static int
1638 c_ni_user (config_entry_t *ce)
1639 {
1640 if (ce->ce_vardata == NULL)
1641 PARAM_ERROR (ce);
1642
1643 if (nicksvs.user != NULL)
1644 sfree (nicksvs.user);
1645 nicksvs.user = sstrdup (ce->ce_vardata);
1646
1647 return 0;
1648 }
1649
1650 static int
1651 c_ni_host (config_entry_t *ce)
1652 {
1653 if (ce->ce_vardata == NULL)
1654 PARAM_ERROR (ce);
1655
1656 if (nicksvs.host != NULL)
1657 sfree (nicksvs.host);
1658 nicksvs.host = sstrdup (ce->ce_vardata);
1659
1660 return 0;
1661 }
1662
1663 static int
1664 c_ni_real (config_entry_t *ce)
1665 {
1666 if (ce->ce_vardata == NULL)
1667 PARAM_ERROR (ce);
1668
1669 if (nicksvs.real != NULL)
1670 sfree (nicksvs.real);
1671 nicksvs.real = sstrdup (ce->ce_vardata);
1672
1673 return 0;
1674 }
1675
1676 static int
1677 c_ni_spam (config_entry_t *ce)
1678 {
1679 nicksvs.spam = true;
1680 return 0;
1681 }
1682
1683 static int
1684 c_ni_no_nick_ownership (config_entry_t *ce)
1685 {
1686 nicksvs.no_nick_ownership = true;
1687 return 0;
1688 }
1689
1690 static int
1691 c_ni_expire (config_entry_t *ce)
1692 {
1693 if (ce->ce_vardata == NULL)
1694 PARAM_ERROR (ce);
1695
1696 nicksvs.expiry = (ce->ce_vardatanum * 60 * 60 * 24);
1697
1698 return 0;
1699 }
1700
1701 static int
1702 c_ss_nick (config_entry_t *ce)
1703 {
1704 if (ce->ce_vardata == NULL)
1705 PARAM_ERROR (ce);
1706
1707 if (saslsvs.nick != NULL)
1708 sfree (saslsvs.nick);
1709 saslsvs.nick = sstrdup (ce->ce_vardata);
1710
1711 return 0;
1712 }
1713
1714 static int
1715 c_ss_user (config_entry_t *ce)
1716 {
1717 if (ce->ce_vardata == NULL)
1718 PARAM_ERROR (ce);
1719
1720 if (saslsvs.user != NULL)
1721 sfree (saslsvs.user);
1722 saslsvs.user = sstrdup (ce->ce_vardata);
1723
1724 return 0;
1725 }
1726
1727 static int
1728 c_ss_host (config_entry_t *ce)
1729 {
1730 if (ce->ce_vardata == NULL)
1731 PARAM_ERROR (ce);
1732
1733 if (saslsvs.host != NULL)
1734 sfree (saslsvs.host);
1735 saslsvs.host = sstrdup (ce->ce_vardata);
1736
1737 return 0;
1738 }
1739
1740 static int
1741 c_ss_real (config_entry_t *ce)
1742 {
1743 if (ce->ce_vardata == NULL)
1744 PARAM_ERROR (ce);
1745
1746 if (saslsvs.real != NULL)
1747 sfree (saslsvs.real);
1748 saslsvs.real = sstrdup (ce->ce_vardata);
1749
1750 return 0;
1751 }
1752
1753 static int
1754 c_ms_nick (config_entry_t *ce)
1755 {
1756 if (ce->ce_vardata == NULL)
1757 PARAM_ERROR (ce);
1758
1759 if (memosvs.nick != NULL)
1760 sfree (memosvs.nick);
1761 memosvs.nick = sstrdup (ce->ce_vardata);
1762
1763 return 0;
1764 }
1765
1766 static int
1767 c_ms_user (config_entry_t *ce)
1768 {
1769 if (ce->ce_vardata == NULL)
1770 PARAM_ERROR (ce);
1771
1772 if (memosvs.user != NULL)
1773 sfree (memosvs.user);
1774 memosvs.user = sstrdup (ce->ce_vardata);
1775
1776 return 0;
1777 }
1778
1779 static int
1780 c_ms_host (config_entry_t *ce)
1781 {
1782 if (ce->ce_vardata == NULL)
1783 PARAM_ERROR (ce);
1784
1785 if (memosvs.host != NULL)
1786 sfree (memosvs.host);
1787 memosvs.host = sstrdup (ce->ce_vardata);
1788
1789 return 0;
1790 }
1791
1792 static int
1793 c_ms_real (config_entry_t *ce)
1794 {
1795 if (ce->ce_vardata == NULL)
1796 PARAM_ERROR (ce);
1797
1798 if (memosvs.real != NULL)
1799 sfree (memosvs.real);
1800 memosvs.real = sstrdup (ce->ce_vardata);
1801
1802 return 0;
1803 }
1804
1805 static int
1806 c_gs_nick (config_entry_t *ce)
1807 {
1808 if (ce->ce_vardata == NULL)
1809 PARAM_ERROR (ce);
1810
1811 if (gamesvs.nick != NULL)
1812 sfree (gamesvs.nick);
1813 gamesvs.nick = sstrdup (ce->ce_vardata);
1814
1815 return 0;
1816 }
1817
1818 static int
1819 c_gs_user (config_entry_t *ce)
1820 {
1821 if (ce->ce_vardata == NULL)
1822 PARAM_ERROR (ce);
1823
1824 if (gamesvs.user != NULL)
1825 sfree (gamesvs.user);
1826 gamesvs.user = sstrdup (ce->ce_vardata);
1827
1828 return 0;
1829 }
1830
1831 static int
1832 c_gs_host (config_entry_t *ce)
1833 {
1834 if (ce->ce_vardata == NULL)
1835 PARAM_ERROR (ce);
1836
1837 if (gamesvs.host != NULL)
1838 sfree (gamesvs.host);
1839 gamesvs.host = sstrdup (ce->ce_vardata);
1840
1841 return 0;
1842 }
1843
1844 static int
1845 c_gs_real (config_entry_t *ce)
1846 {
1847 if (ce->ce_vardata == NULL)
1848 PARAM_ERROR (ce);
1849
1850 if (gamesvs.real != NULL)
1851 sfree (gamesvs.real);
1852 gamesvs.real = sstrdup (ce->ce_vardata);
1853
1854 return 0;
1855 }
1856
1857 static int
1858 c_gl_nick (config_entry_t *ce)
1859 {
1860 if (ce->ce_vardata == NULL)
1861 PARAM_ERROR (ce);
1862
1863 if (globsvs.nick != NULL)
1864 sfree (globsvs.nick);
1865 globsvs.nick = sstrdup (ce->ce_vardata);
1866
1867 return 0;
1868 }
1869
1870 static int
1871 c_gl_user (config_entry_t *ce)
1872 {
1873 if (ce->ce_vardata == NULL)
1874 PARAM_ERROR (ce);
1875
1876 if (globsvs.user != NULL)
1877 sfree (globsvs.user);
1878 globsvs.user = sstrdup (ce->ce_vardata);
1879
1880 return 0;
1881 }
1882
1883 static int
1884 c_gl_host (config_entry_t *ce)
1885 {
1886 if (ce->ce_vardata == NULL)
1887 PARAM_ERROR (ce);
1888
1889 if (globsvs.host != NULL)
1890 sfree (globsvs.host);
1891 globsvs.host = sstrdup (ce->ce_vardata);
1892
1893 return 0;
1894 }
1895
1896 static int
1897 c_gl_real (config_entry_t *ce)
1898 {
1899 if (ce->ce_vardata == NULL)
1900 PARAM_ERROR (ce);
1901
1902 if (globsvs.real != NULL)
1903 sfree (globsvs.real);
1904 globsvs.real = sstrdup (ce->ce_vardata);
1905
1906 return 0;
1907 }
1908
1909 static int
1910 c_db_user (config_entry_t *ce)
1911 {
1912 if (ce->ce_vardata == NULL)
1913 PARAM_ERROR (ce);
1914
1915 if (database_options.user != NULL)
1916 sfree (database_options.user);
1917 database_options.user = sstrdup (ce->ce_vardata);
1918
1919 return 0;
1920 }
1921
1922 static int
1923 c_db_host (config_entry_t *ce)
1924 {
1925 if (ce->ce_vardata == NULL)
1926 PARAM_ERROR (ce);
1927
1928 if (database_options.host != NULL)
1929 sfree (database_options.host);
1930 database_options.host = sstrdup (ce->ce_vardata);
1931
1932 return 0;
1933 }
1934
1935 static int
1936 c_db_password (config_entry_t *ce)
1937 {
1938 if (ce->ce_vardata == NULL)
1939 PARAM_ERROR (ce);
1940
1941 if (database_options.pass != NULL)
1942 sfree (database_options.pass);
1943 database_options.pass = sstrdup (ce->ce_vardata);
1944
1945 return 0;
1946 }
1947
1948 static int
1949 c_db_database (config_entry_t *ce)
1950 {
1951 if (ce->ce_vardata == NULL)
1952 PARAM_ERROR (ce);
1953
1954 if (database_options.database != NULL)
1955 sfree (database_options.database);
1956 database_options.database = sstrdup (ce->ce_vardata);
1957
1958 return 0;
1959 }
1960
1961 static int
1962 c_db_port (config_entry_t *ce)
1963 {
1964 if (ce->ce_vardatanum == 0)
1965 PARAM_ERROR (ce);
1966
1967 database_options.port = ce->ce_vardatanum;
1968
1969 return 0;
1970 }
1971
1972 static int
1973 c_logfile (config_entry_t *ce)
1974 {
1975 config_entry_t *flce;
1976 unsigned int logval = 0;
1977
1978 if (ce->ce_vardata == NULL)
1979 PARAM_ERROR (ce);
1980
1981 for (flce = ce->ce_entries; flce; flce = flce->ce_next)
1982 {
1983 int val;
1984
1985 val = token_to_value (logflags, flce->ce_varname);
1986
1987 if ((val != TOKEN_UNMATCHED) && (val != TOKEN_ERROR))
1988 logval |= val;
1989 else
1990 {
1991 slog (LG_INFO, "%s:%d: unknown flag: %s", flce->ce_fileptr->cf_filename, flce->ce_varlinenum, flce->ce_varname);
1992 }
1993 }
1994
1995 logfile_new (ce->ce_vardata, logval);
1996
1997 return 0;
1998 }
1999
2000 bool
2001 conf_rehash (void)
2002 {
2003 me_t hold_me;
2004 char *oldsnoop;
2005 config_file_t *cfp;
2006
2007 /* we're rehashing */
2008 slog (LG_INFO, "conf_rehash(): rehashing");
2009 runflags |= RF_REHASHING;
2010
2011 errno = 0;
2012 cfp = config_load (config_file);
2013 if (cfp == NULL)
2014 {
2015 slog (LG_ERROR, "conf_rehash(): unable to load configuration file: %s, aborting rehash", strerror (errno));
2016 runflags &= ~RF_REHASHING;
2017 return false;
2018 }
2019
2020 hold_me = me;
2021
2022 oldsnoop = config_options.chan != NULL ? sstrdup (config_options.chan) : NULL;
2023
2024 /* reset everything */
2025 conf_init ();
2026 mark_all_illegal ();
2027 log_shutdown ();
2028
2029 /* now reload */
2030 log_open ();
2031 conf_process (cfp);
2032 config_free (cfp);
2033 ConfTable::callback.ready ();
2034
2035 /* now recheck */
2036 if (!conf_check ())
2037 {
2038 slog (LG_ERROR, "conf_rehash(): conf file was malformed, aborting rehash");
2039
2040 /* freeing the new conf strings */
2041 sfree (chansvs.nick);
2042 me.fini ();
2043
2044 /* return everything to the way it was before */
2045 me = hold_me;
2046
2047 /* not fully ok, oh well */
2048 unmark_all_illegal ();
2049
2050 sfree (oldsnoop);
2051
2052 runflags &= ~RF_REHASHING;
2053 return false;
2054 }
2055
2056 if (oldsnoop != NULL || config_options.chan != NULL)
2057 {
2058 if (config_options.chan == NULL)
2059 partall (oldsnoop);
2060 else if (oldsnoop == NULL)
2061 joinall (config_options.chan);
2062 else if (strcmp (oldsnoop, config_options.chan))
2063 {
2064 partall (oldsnoop);
2065 joinall (config_options.chan);
2066 }
2067 }
2068
2069 remove_illegals ();
2070
2071 sfree (oldsnoop);
2072
2073 runflags &= ~RF_REHASHING;
2074 return true;
2075 }
2076
2077 bool
2078 conf_check (void)
2079 {
2080 if (!me.name)
2081 {
2082 slog (LG_ERROR, "conf_check(): no `name' set in %s", config_file);
2083 return false;
2084 }
2085
2086 /* The following checks could perhaps be stricter */
2087 if (!strchr (me.name, '.') || strchr ("!\"#$%&+,-./:@", me.name[0]) || strchr (me.name, ' '))
2088 {
2089 slog (LG_ERROR, "conf_check(): bogus `name' in %s (did you specify a valid server name?)", config_file);
2090 return false;
2091 }
2092
2093 if (isdigit (me.name[0]))
2094 slog (LG_ERROR, "conf_check(): `name' in %s starts with a digit, probably invalid (continuing anyway)", config_file);
2095
2096 if (!me.desc)
2097 me.desc = sstrdup ("Ermyth IRC Services");
2098
2099 if ((!me.recontime) || (me.recontime < 10))
2100 {
2101 slog (LG_INFO, "conf_check(): invalid `recontime' set in %s; " "defaulting to 10", config_file);
2102 me.recontime = 10;
2103 }
2104
2105 if (!me.netname)
2106 {
2107 slog (LG_INFO, "conf_check(): no `netname' set in %s", config_file);
2108 return false;
2109 }
2110
2111 if (!me.adminname)
2112 {
2113 slog (LG_INFO, "conf_check(): no `adminname' set in %s", config_file);
2114 return false;
2115 }
2116
2117 if (!me.adminemail)
2118 {
2119 slog (LG_INFO, "conf_check(): no `adminemail' set in %s", config_file);
2120 return false;
2121 }
2122
2123 if (!me.mta && me.auth == AUTH_EMAIL)
2124 {
2125 slog (LG_INFO, "conf_check(): no `mta' set in %s (but `auth' is email)", config_file);
2126 return false;
2127 }
2128
2129 if (!me.maxlogins)
2130 {
2131 slog (LG_INFO, "conf_check(): no `maxlogins' set in %s; " "defaulting to 5", config_file);
2132 me.maxlogins = 5;
2133 }
2134
2135 if (!me.maxusers)
2136 {
2137 slog (LG_INFO, "conf_check(): no `maxusers' set in %s; " "defaulting to 5", config_file);
2138 me.maxusers = 5;
2139 }
2140
2141 if (!me.maxnicks)
2142 {
2143 if (!nicksvs.no_nick_ownership)
2144 slog (LG_INFO, "conf_check(): no `maxnicks' set in %s; " "defaulting to 5", config_file);
2145 me.maxnicks = 5;
2146 }
2147
2148 if (!me.maxchans)
2149 {
2150 slog (LG_INFO, "conf_check(): no `maxchans' set in %s; " "defaulting to 5", config_file);
2151 me.maxchans = 5;
2152 }
2153
2154 if (!me.emaillimit)
2155 {
2156 slog (LG_INFO, "conf_check(): no `emaillimit' set in %s; " "defaulting to 10", config_file);
2157 me.emaillimit = 10;
2158 }
2159
2160 if (!me.emailtime)
2161 {
2162 slog (LG_INFO, "conf_check(): no `emailtime' set in %s; " "defaulting to 300", config_file);
2163 me.emailtime = 300;
2164 }
2165
2166 if (me.auth != 0 && me.auth != 1)
2167 {
2168 slog (LG_INFO, "conf_check(): no `auth' set in %s; " "defaulting to NONE", config_file);
2169 me.auth = AUTH_NONE;
2170 }
2171
2172 if (!chansvs.nick || !chansvs.user || !chansvs.host || !chansvs.real)
2173 {
2174 slog (LG_ERROR, "conf_check(): invalid chanserv{} block in %s", config_file);
2175 return false;
2176 }
2177
2178 if ((strchr (chansvs.user, ' ')) || (strlen (chansvs.user) > 10))
2179 {
2180 slog (LG_ERROR, "conf_check(): invalid `chanserv::user' in %s", config_file);
2181 return false;
2182 }
2183
2184 /* we know ca_all now */
2185 chansvs.ca_vop &= ca_all;
2186 chansvs.ca_hop &= ca_all;
2187 chansvs.ca_aop &= ca_all;
2188 chansvs.ca_sop &= ca_all;
2189 /* chansvs.ca_hop may be equal to chansvs.ca_vop to disable HOP */
2190 if (!chansvs.ca_vop || !chansvs.ca_hop || !chansvs.ca_aop || !chansvs.ca_sop || chansvs.ca_vop == chansvs.ca_aop || chansvs.ca_vop == chansvs.ca_sop || chansvs.ca_hop == chansvs.ca_aop || chansvs.ca_hop == chansvs.ca_sop || chansvs.ca_aop == chansvs.ca_sop)
2191 {
2192 slog (LG_INFO, "conf_check(): invalid xop levels in %s, using defaults", config_file);
2193 chansvs.ca_vop = CA_VOP_DEF & ca_all;
2194 chansvs.ca_hop = CA_HOP_DEF & ca_all;
2195 chansvs.ca_aop = CA_AOP_DEF & ca_all;
2196 chansvs.ca_sop = CA_SOP_DEF & ca_all;
2197 }
2198
2199 if (config_options.flood_msgs && !config_options.flood_time)
2200 config_options.flood_time = 10;
2201
2202 if (!config_options.default_clone_limit)
2203 config_options.default_clone_limit = 6;
2204
2205 /* recall that commit_interval is in seconds */
2206 if ((!config_options.commit_interval) || (config_options.commit_interval < 60) || (config_options.commit_interval > 3600))
2207 {
2208 slog (LG_INFO, "conf_check(): invalid `commit_interval' set in %s; " "defaulting to 5 minutes", config_file);
2209 config_options.commit_interval = 300;
2210 }
2211
2212 return true;
2213 }