]> jfr.im git - irc/freenode/solanum.git/blob - modules/m_info.c
693882f6cb1bb2dfdb6c45264c1d8e2fd6b4f6db
[irc/freenode/solanum.git] / modules / m_info.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * m_info.c: Sends information about the server.
4 *
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
23 */
24
25 #include "stdinc.h"
26 #include "m_info.h"
27 #include "channel.h"
28 #include "client.h"
29 #include "match.h"
30 #include "ircd.h"
31 #include "hook.h"
32 #include "numeric.h"
33 #include "s_serv.h"
34 #include "s_user.h"
35 #include "send.h"
36 #include "s_conf.h"
37 #include "msg.h"
38 #include "parse.h"
39 #include "modules.h"
40 #include "s_newconf.h"
41
42 static const char info_desc[] =
43 "Provides the INFO command for retrieving server copyright, credits, and other info";
44
45 static void send_conf_options(struct Client *source_p);
46 static void send_birthdate_online_time(struct Client *source_p);
47 static void send_info_text(struct Client *source_p);
48 static void info_spy(struct Client *);
49
50 static void m_info(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
51 static void mo_info(struct MsgBuf *, struct Client *, struct Client *, int, const char **);
52
53 struct Message info_msgtab = {
54 "INFO", 0, 0, 0, 0,
55 {mg_unreg, {m_info, 0}, {mo_info, 0}, mg_ignore, mg_ignore, {mo_info, 0}}
56 };
57
58 int doing_info_hook;
59
60 mapi_clist_av1 info_clist[] = { &info_msgtab, NULL };
61 mapi_hlist_av1 info_hlist[] = {
62 { "doing_info", &doing_info_hook },
63 { NULL, NULL }
64 };
65
66 DECLARE_MODULE_AV2(info, NULL, NULL, info_clist, info_hlist, NULL, NULL, NULL, info_desc);
67
68 enum info_output_type {
69 OUTPUT_STRING, /* Output option as %s w/ dereference */
70 OUTPUT_STRING_PTR, /* Output option as %s w/out deference */
71 OUTPUT_DECIMAL, /* Output option as decimal (%d) */
72 OUTPUT_BOOLEAN, /* Output option as "ON" or "OFF" */
73 OUTPUT_BOOLEAN_YN, /* Output option as "YES" or "NO" */
74 OUTPUT_INTBOOL, /* BOOLEAN encoded as an int */
75 OUTPUT_INTBOOL_YN, /* BOOLEAN_YN encoded as an int */
76 OUTPUT_YESNOMASK, /* Output option as "YES/NO/MASKED" */
77 };
78
79 #define INFO_STRING(ptr) OUTPUT_STRING, .option.string_p = (ptr)
80 #define INFO_STRING_PTR(ptr) OUTPUT_STRING_PTR, .option.string = (ptr)
81 #define INFO_BOOLEAN(ptr) OUTPUT_BOOLEAN, .option.bool_ = (ptr)
82 #define INFO_BOOLEAN_YN(ptr) OUTPUT_BOOLEAN_YN, .option.bool_ = (ptr)
83 #define INFO_INTBOOL(ptr) OUTPUT_INTBOOL, .option.int_ = (ptr)
84 #define INFO_INTBOOL_YN(ptr) OUTPUT_INTBOOL_YN, .option.int_ = (ptr)
85 #define INFO_YESNOMASK(ptr) OUTPUT_YESNOMASK, .option.int_ = (ptr)
86 #define INFO_DECIMAL(ptr) OUTPUT_DECIMAL, .option.int_ = (ptr)
87
88 struct InfoStruct
89 {
90 const char *name;
91 const char *desc;
92 enum info_output_type output_type;
93 union
94 {
95 const int *int_;
96 const bool *bool_;
97 char **string_p;
98 char *string;
99 } option;
100 };
101
102 /* *INDENT-OFF* */
103 static struct InfoStruct info_table[] = {
104
105 {
106 "opers_see_all_users",
107 "Farconnect notices available or operspy accountability limited",
108 INFO_BOOLEAN(&opers_see_all_users)
109 },
110 {
111 "max_connections",
112 "Max number connections",
113 INFO_DECIMAL(&maxconnections),
114 },
115 {
116 "anti_nick_flood",
117 "NICK flood protection",
118 INFO_INTBOOL(&ConfigFileEntry.anti_nick_flood),
119 },
120 {
121 "anti_spam_exit_message_time",
122 "Duration a client must be connected for to have an exit message",
123 INFO_DECIMAL(&ConfigFileEntry.anti_spam_exit_message_time),
124 },
125 {
126 "caller_id_wait",
127 "Minimum delay between notifying UMODE +g users of messages",
128 INFO_DECIMAL(&ConfigFileEntry.caller_id_wait),
129 },
130 {
131 "client_exit",
132 "Prepend 'Quit:' to user QUIT messages",
133 INFO_INTBOOL(&ConfigFileEntry.client_exit),
134 },
135 {
136 "client_flood_max_lines",
137 "Number of lines before a client Excess Flood's",
138 INFO_DECIMAL(&ConfigFileEntry.client_flood_max_lines),
139 },
140 {
141 "client_flood_burst_rate",
142 "Maximum lines per second during flood grace period",
143 INFO_DECIMAL(&ConfigFileEntry.client_flood_burst_rate),
144 },
145 {
146 "client_flood_burst_max",
147 "Number of lines to process at once before delaying",
148 INFO_DECIMAL(&ConfigFileEntry.client_flood_burst_max),
149 },
150 {
151 "client_flood_message_num",
152 "Number of messages to allow per client_flood_message_time outside of burst",
153 INFO_DECIMAL(&ConfigFileEntry.client_flood_message_num),
154 },
155 {
156 "client_flood_message_time",
157 "Time to allow per client_flood_message_num outside of burst",
158 INFO_DECIMAL(&ConfigFileEntry.client_flood_message_time),
159 },
160 {
161 "post_registration_delay",
162 "Time to wait before processing commands from a new client",
163 INFO_DECIMAL(&ConfigFileEntry.post_registration_delay),
164 },
165 {
166 "connect_timeout",
167 "Connect timeout for connections to servers",
168 INFO_DECIMAL(&ConfigFileEntry.connect_timeout),
169 },
170 {
171 "default_ident_timeout",
172 "Amount of time the server waits for ident responses from clients",
173 INFO_DECIMAL(&ConfigFileEntry.default_ident_timeout),
174 },
175 {
176 "default_floodcount",
177 "Startup value of FLOODCOUNT",
178 INFO_DECIMAL(&ConfigFileEntry.default_floodcount),
179 },
180 {
181 "default_adminstring",
182 "Default adminstring at startup.",
183 INFO_STRING(&ConfigFileEntry.default_adminstring),
184 },
185 {
186 "default_operstring",
187 "Default operstring at startup.",
188 INFO_STRING(&ConfigFileEntry.default_operstring),
189 },
190 {
191 "servicestring",
192 "String shown in whois for opered services.",
193 INFO_STRING(&ConfigFileEntry.servicestring),
194 },
195 {
196 "disable_auth",
197 "Controls whether auth checking is disabled or not",
198 INFO_INTBOOL_YN(&ConfigFileEntry.disable_auth),
199 },
200 {
201 "disable_fake_channels",
202 "Controls whether bold etc are disabled for JOIN",
203 INFO_INTBOOL_YN(&ConfigFileEntry.disable_fake_channels),
204 },
205 {
206 "dots_in_ident",
207 "Number of permissible dots in an ident",
208 INFO_DECIMAL(&ConfigFileEntry.dots_in_ident),
209 },
210 {
211 "failed_oper_notice",
212 "Inform opers if someone /oper's with the wrong password",
213 INFO_INTBOOL(&ConfigFileEntry.failed_oper_notice),
214 },
215 {
216 "fname_userlog",
217 "User log file",
218 INFO_STRING(&ConfigFileEntry.fname_userlog),
219 },
220 {
221 "fname_fuserlog",
222 "Failed user log file",
223 INFO_STRING(&ConfigFileEntry.fname_fuserlog),
224 },
225
226 {
227 "fname_operlog",
228 "Operator log file",
229 INFO_STRING(&ConfigFileEntry.fname_operlog),
230 },
231 {
232 "fname_foperlog",
233 "Failed operator log file",
234 INFO_STRING(&ConfigFileEntry.fname_foperlog),
235 },
236 {
237 "fname_serverlog",
238 "Server connect/disconnect log file",
239 INFO_STRING(&ConfigFileEntry.fname_serverlog),
240 },
241 {
242 "fname_killlog",
243 "KILL log file",
244 INFO_STRING(&ConfigFileEntry.fname_killlog),
245 },
246 {
247 "fname_klinelog",
248 "KLINE etc log file",
249 INFO_STRING(&ConfigFileEntry.fname_klinelog),
250 },
251 {
252 "fname_operspylog",
253 "Oper spy log file",
254 INFO_STRING(&ConfigFileEntry.fname_operspylog),
255 },
256 {
257 "fname_ioerrorlog",
258 "IO error log file",
259 INFO_STRING(&ConfigFileEntry.fname_ioerrorlog),
260 },
261 {
262 "global_snotices",
263 "Send out certain server notices globally",
264 INFO_INTBOOL_YN(&ConfigFileEntry.global_snotices),
265 },
266 {
267 "hide_error_messages",
268 "Hide ERROR messages coming from servers",
269 INFO_YESNOMASK(&ConfigFileEntry.hide_error_messages),
270 },
271 {
272 "hide_spoof_ips",
273 "Hide IPs of spoofed users",
274 INFO_INTBOOL_YN(&ConfigFileEntry.hide_spoof_ips),
275 },
276 {
277 "kline_reason",
278 "K-lined clients sign off with this reason",
279 INFO_STRING(&ConfigFileEntry.kline_reason),
280 },
281 {
282 "dline_with_reason",
283 "Display D-line reason to client on disconnect",
284 INFO_INTBOOL_YN(&ConfigFileEntry.dline_with_reason),
285 },
286 {
287 "kline_with_reason",
288 "Display K-line reason to client on disconnect",
289 INFO_INTBOOL_YN(&ConfigFileEntry.kline_with_reason),
290 },
291 {
292 "max_accept",
293 "Maximum nicknames on accept list",
294 INFO_DECIMAL(&ConfigFileEntry.max_accept),
295 },
296 {
297 "max_nick_changes",
298 "NICK change threshold setting",
299 INFO_DECIMAL(&ConfigFileEntry.max_nick_changes),
300 },
301 {
302 "max_nick_time",
303 "NICK flood protection time interval",
304 INFO_DECIMAL(&ConfigFileEntry.max_nick_time),
305 },
306 {
307 "max_targets",
308 "The maximum number of PRIVMSG/NOTICE targets",
309 INFO_DECIMAL(&ConfigFileEntry.max_targets),
310 },
311 {
312 "min_nonwildcard",
313 "Minimum non-wildcard chars in K lines",
314 INFO_DECIMAL(&ConfigFileEntry.min_nonwildcard),
315 },
316 {
317 "min_nonwildcard_simple",
318 "Minimum non-wildcard chars in xlines/resvs",
319 INFO_DECIMAL(&ConfigFileEntry.min_nonwildcard_simple),
320 },
321 {
322 "network_name",
323 "Network name",
324 INFO_STRING(&ServerInfo.network_name),
325 },
326 {
327 "nick_delay",
328 "Delay nicks are locked for on split",
329 INFO_DECIMAL(&ConfigFileEntry.nick_delay),
330 },
331 {
332 "no_oper_flood",
333 "Disable flood control for operators",
334 INFO_INTBOOL(&ConfigFileEntry.no_oper_flood),
335 },
336 {
337 "non_redundant_klines",
338 "Check for and disallow redundant K-lines",
339 INFO_INTBOOL(&ConfigFileEntry.non_redundant_klines),
340 },
341 {
342 "operspy_admin_only",
343 "Send +Z operspy notices to admins only",
344 INFO_INTBOOL(&ConfigFileEntry.operspy_admin_only),
345 },
346 {
347 "operspy_dont_care_user_info",
348 "Remove accountability and some '!' requirement from non-channel operspy",
349 INFO_INTBOOL(&ConfigFileEntry.operspy_dont_care_user_info),
350 },
351 {
352 "pace_wait",
353 "Minimum delay between uses of certain commands",
354 INFO_DECIMAL(&ConfigFileEntry.pace_wait),
355 },
356 {
357 "pace_wait_simple",
358 "Minimum delay between less intensive commands",
359 INFO_DECIMAL(&ConfigFileEntry.pace_wait_simple),
360 },
361 {
362 "ping_cookie",
363 "Require ping cookies to connect",
364 INFO_INTBOOL(&ConfigFileEntry.ping_cookie),
365 },
366 {
367 "reject_after_count",
368 "Client rejection threshold setting",
369 INFO_DECIMAL(&ConfigFileEntry.reject_after_count),
370 },
371 {
372 "reject_ban_time",
373 "Client rejection time interval",
374 INFO_DECIMAL(&ConfigFileEntry.reject_ban_time),
375 },
376 {
377 "reject_duration",
378 "Client rejection cache duration",
379 INFO_DECIMAL(&ConfigFileEntry.reject_duration),
380 },
381 {
382 "short_motd",
383 "Do not show MOTD; only tell clients they should read it",
384 INFO_INTBOOL_YN(&ConfigFileEntry.short_motd),
385 },
386 {
387 "stats_e_disabled",
388 "STATS e output is disabled",
389 INFO_INTBOOL_YN(&ConfigFileEntry.stats_e_disabled),
390 },
391 {
392 "stats_c_oper_only",
393 "STATS C output is only shown to operators",
394 INFO_INTBOOL_YN(&ConfigFileEntry.stats_c_oper_only),
395 },
396 {
397 "stats_h_oper_only",
398 "STATS H output is only shown to operators",
399 INFO_INTBOOL_YN(&ConfigFileEntry.stats_h_oper_only),
400 },
401 {
402 "stats_i_oper_only",
403 "STATS I output is only shown to operators",
404 INFO_YESNOMASK(&ConfigFileEntry.stats_i_oper_only),
405 },
406 {
407 "stats_k_oper_only",
408 "STATS K output is only shown to operators",
409 INFO_YESNOMASK(&ConfigFileEntry.stats_k_oper_only),
410 },
411 {
412 "stats_o_oper_only",
413 "STATS O output is only shown to operators",
414 INFO_INTBOOL_YN(&ConfigFileEntry.stats_o_oper_only),
415 },
416 {
417 "stats_P_oper_only",
418 "STATS P is only shown to operators",
419 INFO_INTBOOL_YN(&ConfigFileEntry.stats_P_oper_only),
420 },
421 {
422 "stats_y_oper_only",
423 "STATS Y is only shown to operators",
424 INFO_INTBOOL_YN(&ConfigFileEntry.stats_y_oper_only),
425 },
426 {
427 "throttle_count",
428 "Connection throttle threshold",
429 INFO_DECIMAL(&ConfigFileEntry.throttle_count),
430 },
431 {
432 "throttle_duration",
433 "Connection throttle duration",
434 INFO_DECIMAL(&ConfigFileEntry.throttle_duration),
435 },
436 {
437 "tkline_expire_notices",
438 "Notices given to opers when tklines expire",
439 INFO_INTBOOL(&ConfigFileEntry.tkline_expire_notices),
440 },
441 {
442 "ts_max_delta",
443 "Maximum permitted TS delta from another server",
444 INFO_DECIMAL(&ConfigFileEntry.ts_max_delta),
445 },
446 {
447 "ts_warn_delta",
448 "Maximum permitted TS delta before displaying a warning",
449 INFO_DECIMAL(&ConfigFileEntry.ts_warn_delta),
450 },
451 {
452 "warn_no_nline",
453 "Display warning if connecting server lacks connect block",
454 INFO_INTBOOL(&ConfigFileEntry.warn_no_nline),
455 },
456 {
457 "use_propagated_bans",
458 "KLINE sets fully propagated bans",
459 INFO_INTBOOL(&ConfigFileEntry.use_propagated_bans),
460 },
461 {
462 "max_ratelimit_tokens",
463 "The maximum number of tokens that can be accumulated for executing rate-limited commands",
464 INFO_DECIMAL(&ConfigFileEntry.max_ratelimit_tokens),
465 },
466 {
467 "away_interval",
468 "The minimum time between aways",
469 INFO_DECIMAL(&ConfigFileEntry.away_interval),
470 },
471 {
472 "tls_ciphers_oper_only",
473 "TLS cipher strings are hidden in whois for non-opers",
474 INFO_INTBOOL_YN(&ConfigFileEntry.tls_ciphers_oper_only),
475 },
476 {
477 "default_split_server_count",
478 "Startup value of SPLITNUM",
479 INFO_DECIMAL(&ConfigChannel.default_split_server_count),
480 },
481 {
482 "default_split_user_count",
483 "Startup value of SPLITUSERS",
484 INFO_DECIMAL(&ConfigChannel.default_split_user_count),
485 },
486 {
487 "knock_delay",
488 "Delay between a users KNOCK attempts",
489 INFO_DECIMAL(&ConfigChannel.knock_delay),
490 },
491 {
492 "knock_delay_channel",
493 "Delay between KNOCK attempts to a channel",
494 INFO_DECIMAL(&ConfigChannel.knock_delay_channel),
495 },
496 {
497 "kick_on_split_riding",
498 "Kick users riding splits to join +i or +k channels",
499 INFO_INTBOOL_YN(&ConfigChannel.kick_on_split_riding),
500 },
501 {
502 "disable_local_channels",
503 "Disable local channels (&channels)",
504 INFO_INTBOOL_YN(&ConfigChannel.disable_local_channels),
505 },
506 {
507 "max_bans",
508 "Total +b/e/I/q modes allowed in a channel",
509 INFO_DECIMAL(&ConfigChannel.max_bans),
510 },
511 {
512 "max_bans_large",
513 "Total +b/e/I/q modes allowed in a +L channel",
514 INFO_DECIMAL(&ConfigChannel.max_bans_large),
515 },
516 {
517 "max_chans_per_user",
518 "Maximum number of channels a user can join",
519 INFO_DECIMAL(&ConfigChannel.max_chans_per_user),
520 },
521 {
522 "max_chans_per_user_large",
523 "Maximum extended number of channels a user can join",
524 INFO_DECIMAL(&ConfigChannel.max_chans_per_user_large),
525 },
526 {
527 "no_create_on_split",
528 "Disallow creation of channels when split",
529 INFO_INTBOOL_YN(&ConfigChannel.no_create_on_split),
530 },
531 {
532 "no_join_on_split",
533 "Disallow joining channels when split",
534 INFO_INTBOOL_YN(&ConfigChannel.no_join_on_split),
535 },
536 {
537 "only_ascii_channels",
538 "Controls whether non-ASCII is disabled for JOIN",
539 INFO_INTBOOL_YN(&ConfigChannel.only_ascii_channels),
540 },
541 {
542 "use_except",
543 "Enable chanmode +e (ban exceptions)",
544 INFO_INTBOOL_YN(&ConfigChannel.use_except),
545 },
546 {
547 "use_invex",
548 "Enable chanmode +I (invite exceptions)",
549 INFO_INTBOOL_YN(&ConfigChannel.use_invex),
550 },
551 {
552 "use_forward",
553 "Enable chanmode +f (channel forwarding)",
554 INFO_INTBOOL_YN(&ConfigChannel.use_forward),
555 },
556 {
557 "use_knock",
558 "Enable /KNOCK",
559 INFO_INTBOOL_YN(&ConfigChannel.use_knock),
560 },
561 {
562 "resv_forcepart",
563 "Force-part local users on channel RESV",
564 INFO_INTBOOL_YN(&ConfigChannel.resv_forcepart),
565 },
566 {
567 "opmod_send_statusmsg",
568 "Send messages to @#channel if affected by +z",
569 INFO_INTBOOL_YN(&ConfigChannel.opmod_send_statusmsg),
570 },
571 {
572 "disable_hidden",
573 "Prevent servers from hiding themselves from a flattened /links",
574 INFO_INTBOOL_YN(&ConfigServerHide.disable_hidden),
575 },
576 {
577 "flatten_links",
578 "Flatten /links list",
579 INFO_INTBOOL_YN(&ConfigServerHide.flatten_links),
580 },
581 {
582 "hidden",
583 "Hide this server from a flattened /links on remote servers",
584 INFO_INTBOOL_YN(&ConfigServerHide.hidden),
585 },
586 {
587 "links_delay",
588 "Links rehash delay",
589 INFO_DECIMAL(&ConfigServerHide.links_delay),
590 },
591
592 { NULL, NULL, 0, { NULL } },
593 };
594 /* *INDENT-ON* */
595
596 /*
597 ** m_info
598 ** parv[1] = servername
599 */
600 static void
601 m_info(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
602 {
603 static time_t last_used = 0L;
604
605 if((last_used + ConfigFileEntry.pace_wait) > rb_current_time())
606 {
607 /* safe enough to give this on a local connect only */
608 sendto_one(source_p, form_str(RPL_LOAD2HI),
609 me.name, source_p->name, "INFO");
610 sendto_one_numeric(source_p, RPL_ENDOFINFO, form_str(RPL_ENDOFINFO));
611 return;
612 }
613 else
614 last_used = rb_current_time();
615
616 if(hunt_server(client_p, source_p, ":%s INFO :%s", 1, parc, parv) != HUNTED_ISME)
617 return;
618
619 info_spy(source_p);
620
621 send_info_text(source_p);
622 send_birthdate_online_time(source_p);
623
624 sendto_one_numeric(source_p, RPL_ENDOFINFO, form_str(RPL_ENDOFINFO));
625 }
626
627 /*
628 ** mo_info
629 ** parv[1] = servername
630 */
631 static void
632 mo_info(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
633 {
634 if(hunt_server(client_p, source_p, ":%s INFO :%s", 1, parc, parv) == HUNTED_ISME)
635 {
636 info_spy(source_p);
637 send_info_text(source_p);
638
639 if(IsOperGeneral(source_p))
640 {
641 send_conf_options(source_p);
642 sendto_one_numeric(source_p, RPL_INFO, ":%s",
643 rb_lib_version());
644 }
645
646 send_birthdate_online_time(source_p);
647
648 sendto_one_numeric(source_p, RPL_ENDOFINFO, form_str(RPL_ENDOFINFO));
649 }
650 }
651
652 /*
653 * send_info_text
654 *
655 * inputs - client pointer to send info text to
656 * output - none
657 * side effects - info text is sent to client
658 */
659 static void
660 send_info_text(struct Client *source_p)
661 {
662 const char **text = infotext;
663
664 while (*text)
665 {
666 sendto_one_numeric(source_p, RPL_INFO, form_str(RPL_INFO), *text++);
667 }
668
669 sendto_one_numeric(source_p, RPL_INFO, form_str(RPL_INFO), "");
670 }
671
672 /*
673 * send_birthdate_online_time
674 *
675 * inputs - client pointer to send to
676 * output - none
677 * side effects - birthdate and online time are sent
678 */
679 static void
680 send_birthdate_online_time(struct Client *source_p)
681 {
682 char tbuf[26]; /* this needs to be 26 - see ctime_r manpage */
683 sendto_one(source_p, ":%s %d %s :Birth Date: %s, compile # %s",
684 get_id(&me, source_p), RPL_INFO,
685 get_id(source_p, source_p), creation, generation);
686
687 sendto_one(source_p, ":%s %d %s :On-line since %s",
688 get_id(&me, source_p), RPL_INFO,
689 get_id(source_p, source_p), rb_ctime(startup_time, tbuf, sizeof(tbuf)));
690 }
691
692 /*
693 * send_conf_options
694 *
695 * inputs - client pointer to send to
696 * output - none
697 * side effects - send config options to client
698 */
699 static void
700 send_conf_options(struct Client *source_p)
701 {
702 Info *infoptr;
703 int i = 0;
704
705 /*
706 * Now send them a list of all our configuration options
707 * (mostly from defaults.h)
708 */
709 for (infoptr = MyInformation; infoptr->name; infoptr++)
710 {
711 if(infoptr->intvalue)
712 {
713 sendto_one(source_p, ":%s %d %s :%-30s %-16d [%s]",
714 get_id(&me, source_p), RPL_INFO,
715 get_id(source_p, source_p),
716 infoptr->name, infoptr->intvalue,
717 infoptr->desc);
718 }
719 else
720 {
721 sendto_one(source_p, ":%s %d %s :%-30s %-16s [%s]",
722 get_id(&me, source_p), RPL_INFO,
723 get_id(source_p, source_p),
724 infoptr->name, infoptr->strvalue,
725 infoptr->desc);
726 }
727 }
728
729 /*
730 * Parse the info_table[] and do the magic.
731 */
732 for (i = 0; info_table[i].name; i++)
733 {
734 static char opt_buf[BUFSIZE];
735 char *opt_value = opt_buf;
736
737
738 switch (info_table[i].output_type)
739 {
740 case OUTPUT_STRING:
741 {
742 char *option = *info_table[i].option.string_p;
743 opt_value = option != NULL ? option : "NONE";
744 break;
745 }
746 case OUTPUT_STRING_PTR:
747 {
748 char *option = info_table[i].option.string;
749 opt_value = option != NULL ? option : "NONE";
750 break;
751 }
752 case OUTPUT_DECIMAL:
753 {
754 int option = *info_table[i].option.int_;
755 snprintf(opt_buf, sizeof opt_buf, "%d", option);
756 break;
757 }
758 case OUTPUT_BOOLEAN:
759 {
760 bool option = *info_table[i].option.bool_;
761 opt_value = option ? "ON" : "OFF";
762 break;
763 }
764 case OUTPUT_BOOLEAN_YN:
765 {
766 bool option = *info_table[i].option.bool_;
767 opt_value = option ? "YES" : "NO";
768 break;
769 }
770 case OUTPUT_YESNOMASK:
771 {
772 int option = *info_table[i].option.int_;
773 opt_value = option == 0 ? "NO" :
774 option == 1 ? "MASK" :
775 "YES";
776 break;
777 }
778 case OUTPUT_INTBOOL:
779 {
780 bool option = *info_table[i].option.int_;
781 opt_value = option ? "ON" : "OFF";
782 break;
783 }
784 case OUTPUT_INTBOOL_YN:
785 {
786 bool option = *info_table[i].option.int_;
787 opt_value = option ? "YES" : "NO";
788 break;
789 }
790 }
791
792 sendto_one(source_p, ":%s %d %s :%-30s %-16s [%s]",
793 get_id(&me, source_p), RPL_INFO,
794 get_id(source_p, source_p),
795 info_table[i].name,
796 opt_value,
797 info_table[i].desc ? info_table[i].desc : "<none>");
798 }
799
800
801 /* Don't send oper_only_umodes...it's a bit mask, we will have to decode it
802 ** in order for it to show up properly to opers who issue INFO
803 */
804
805 sendto_one_numeric(source_p, RPL_INFO, form_str(RPL_INFO), "");
806 }
807
808 /* info_spy()
809 *
810 * input - pointer to client
811 * output - none
812 * side effects - hook doing_info is called
813 */
814 static void
815 info_spy(struct Client *source_p)
816 {
817 hook_data hd;
818
819 hd.client = source_p;
820 hd.arg1 = hd.arg2 = NULL;
821
822 call_hook(doing_info_hook, &hd);
823 }