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