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