ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/src/conf.C
Revision: 1.7
Committed: Thu Aug 30 19:56:24 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.6: +3 -3 lines
Log Message:
- put faultcodes into their own namespace
- removed old files
- limited header garbage in atheme.h
- macros to inline bools for connection_t::is_*
- put some connection_t functions into the connection_t class

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