]> jfr.im git - solanum.git/blob - modules/m_info.c
Send YES/NO to Davy Jones's Locker.
[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 "kline_delay",
290 OUTPUT_DECIMAL,
291 &ConfigFileEntry.kline_delay,
292 "Duration of time to delay kline checking"
293 },
294 {
295 "kline_reason",
296 OUTPUT_STRING,
297 &ConfigFileEntry.kline_reason,
298 "K-lined clients sign off with this reason"
299 },
300 {
301 "dline_with_reason",
302 OUTPUT_BOOLEAN_YN,
303 &ConfigFileEntry.dline_with_reason,
304 "Display D-line reason to client on disconnect"
305 },
306 {
307 "kline_with_reason",
308 OUTPUT_BOOLEAN_YN,
309 &ConfigFileEntry.kline_with_reason,
310 "Display K-line reason to client on disconnect"
311 },
312 {
313 "max_accept",
314 OUTPUT_DECIMAL,
315 &ConfigFileEntry.max_accept,
316 "Maximum nicknames on accept list",
317 },
318 {
319 "max_nick_changes",
320 OUTPUT_DECIMAL,
321 &ConfigFileEntry.max_nick_changes,
322 "NICK change threshhold setting"
323 },
324 {
325 "max_nick_time",
326 OUTPUT_DECIMAL,
327 &ConfigFileEntry.max_nick_time,
328 "NICK flood protection time interval"
329 },
330 {
331 "max_targets",
332 OUTPUT_DECIMAL,
333 &ConfigFileEntry.max_targets,
334 "The maximum number of PRIVMSG/NOTICE targets"
335 },
336 {
337 "min_nonwildcard",
338 OUTPUT_DECIMAL,
339 &ConfigFileEntry.min_nonwildcard,
340 "Minimum non-wildcard chars in K lines",
341 },
342 {
343 "min_nonwildcard_simple",
344 OUTPUT_DECIMAL,
345 &ConfigFileEntry.min_nonwildcard_simple,
346 "Minimum non-wildcard chars in xlines/resvs",
347 },
348 {
349 "network_name",
350 OUTPUT_STRING,
351 &ServerInfo.network_name,
352 "Network name"
353 },
354 {
355 "nick_delay",
356 OUTPUT_DECIMAL,
357 &ConfigFileEntry.nick_delay,
358 "Delay nicks are locked for on split",
359 },
360 {
361 "no_oper_flood",
362 OUTPUT_BOOLEAN,
363 &ConfigFileEntry.no_oper_flood,
364 "Disable flood control for operators",
365 },
366 {
367 "non_redundant_klines",
368 OUTPUT_BOOLEAN,
369 &ConfigFileEntry.non_redundant_klines,
370 "Check for and disallow redundant K-lines"
371 },
372 {
373 "operspy_admin_only",
374 OUTPUT_BOOLEAN,
375 &ConfigFileEntry.operspy_admin_only,
376 "Send +Z operspy notices to admins only"
377 },
378 {
379 "operspy_dont_care_user_info",
380 OUTPUT_BOOLEAN,
381 &ConfigFileEntry.operspy_dont_care_user_info,
382 "Remove accountability and some '!' requirement from non-channel operspy"
383 },
384 {
385 "pace_wait",
386 OUTPUT_DECIMAL,
387 &ConfigFileEntry.pace_wait,
388 "Minimum delay between uses of certain commands"
389 },
390 {
391 "pace_wait_simple",
392 OUTPUT_DECIMAL,
393 &ConfigFileEntry.pace_wait_simple,
394 "Minimum delay between less intensive commands"
395 },
396 {
397 "ping_cookie",
398 OUTPUT_BOOLEAN,
399 &ConfigFileEntry.ping_cookie,
400 "Require ping cookies to connect",
401 },
402 {
403 "reject_after_count",
404 OUTPUT_DECIMAL,
405 &ConfigFileEntry.reject_after_count,
406 "Client rejection threshold setting",
407 },
408 {
409 "reject_ban_time",
410 OUTPUT_DECIMAL,
411 &ConfigFileEntry.reject_ban_time,
412 "Client rejection time interval",
413 },
414 {
415 "reject_duration",
416 OUTPUT_DECIMAL,
417 &ConfigFileEntry.reject_duration,
418 "Client rejection cache duration",
419 },
420 {
421 "short_motd",
422 OUTPUT_BOOLEAN_YN,
423 &ConfigFileEntry.short_motd,
424 "Do not show MOTD; only tell clients they should read it"
425 },
426 {
427 "stats_e_disabled",
428 OUTPUT_BOOLEAN_YN,
429 &ConfigFileEntry.stats_e_disabled,
430 "STATS e output is disabled",
431 },
432 {
433 "stats_c_oper_only",
434 OUTPUT_BOOLEAN_YN,
435 &ConfigFileEntry.stats_c_oper_only,
436 "STATS C output is only shown to operators",
437 },
438 {
439 "stats_h_oper_only",
440 OUTPUT_BOOLEAN_YN,
441 &ConfigFileEntry.stats_h_oper_only,
442 "STATS H output is only shown to operators",
443 },
444 {
445 "stats_i_oper_only",
446 OUTPUT_BOOLEAN2,
447 &ConfigFileEntry.stats_i_oper_only,
448 "STATS I output is only shown to operators",
449 },
450 {
451 "stats_k_oper_only",
452 OUTPUT_BOOLEAN2,
453 &ConfigFileEntry.stats_k_oper_only,
454 "STATS K output is only shown to operators",
455 },
456 {
457 "stats_o_oper_only",
458 OUTPUT_BOOLEAN_YN,
459 &ConfigFileEntry.stats_o_oper_only,
460 "STATS O output is only shown to operators",
461 },
462 {
463 "stats_P_oper_only",
464 OUTPUT_BOOLEAN_YN,
465 &ConfigFileEntry.stats_P_oper_only,
466 "STATS P is only shown to operators",
467 },
468 {
469 "stats_y_oper_only",
470 OUTPUT_BOOLEAN_YN,
471 &ConfigFileEntry.stats_y_oper_only,
472 "STATS Y is only shown to operators",
473 },
474 {
475 "throttle_count",
476 OUTPUT_DECIMAL,
477 &ConfigFileEntry.throttle_count,
478 "Connection throttle threshold",
479 },
480 {
481 "throttle_duration",
482 OUTPUT_DECIMAL,
483 &ConfigFileEntry.throttle_duration,
484 "Connection throttle duration",
485 },
486 {
487 "tkline_expire_notices",
488 OUTPUT_BOOLEAN,
489 &ConfigFileEntry.tkline_expire_notices,
490 "Notices given to opers when tklines expire"
491 },
492 {
493 "ts_max_delta",
494 OUTPUT_DECIMAL,
495 &ConfigFileEntry.ts_max_delta,
496 "Maximum permitted TS delta from another server"
497 },
498 {
499 "ts_warn_delta",
500 OUTPUT_DECIMAL,
501 &ConfigFileEntry.ts_warn_delta,
502 "Maximum permitted TS delta before displaying a warning"
503 },
504 {
505 "warn_no_nline",
506 OUTPUT_BOOLEAN,
507 &ConfigFileEntry.warn_no_nline,
508 "Display warning if connecting server lacks connect block"
509 },
510 {
511 "use_propagated_bans",
512 OUTPUT_BOOLEAN,
513 &ConfigFileEntry.use_propagated_bans,
514 "KLINE sets fully propagated bans"
515 },
516 {
517 "max_ratelimit_tokens",
518 OUTPUT_DECIMAL,
519 &ConfigFileEntry.max_ratelimit_tokens,
520 "The maximum number of tokens that can be accumulated for executing rate-limited commands",
521 },
522 {
523 "away_interval",
524 OUTPUT_DECIMAL,
525 &ConfigFileEntry.away_interval,
526 "The minimum time between aways",
527 },
528 {
529 "default_split_server_count",
530 OUTPUT_DECIMAL,
531 &ConfigChannel.default_split_server_count,
532 "Startup value of SPLITNUM",
533 },
534 {
535 "default_split_user_count",
536 OUTPUT_DECIMAL,
537 &ConfigChannel.default_split_user_count,
538 "Startup value of SPLITUSERS",
539 },
540 {
541 "knock_delay",
542 OUTPUT_DECIMAL,
543 &ConfigChannel.knock_delay,
544 "Delay between a users KNOCK attempts"
545 },
546 {
547 "knock_delay_channel",
548 OUTPUT_DECIMAL,
549 &ConfigChannel.knock_delay_channel,
550 "Delay between KNOCK attempts to a channel",
551 },
552 {
553 "kick_on_split_riding",
554 OUTPUT_BOOLEAN_YN,
555 &ConfigChannel.kick_on_split_riding,
556 "Kick users riding splits to join +i or +k channels"
557 },
558 {
559 "disable_local_channels",
560 OUTPUT_BOOLEAN_YN,
561 &ConfigChannel.disable_local_channels,
562 "Disable local channels (&channels)"
563 },
564 {
565 "max_bans",
566 OUTPUT_DECIMAL,
567 &ConfigChannel.max_bans,
568 "Total +b/e/I/q modes allowed in a channel",
569 },
570 {
571 "max_bans_large",
572 OUTPUT_DECIMAL,
573 &ConfigChannel.max_bans_large,
574 "Total +b/e/I/q modes allowed in a +L channel",
575 },
576 {
577 "max_chans_per_user",
578 OUTPUT_DECIMAL,
579 &ConfigChannel.max_chans_per_user,
580 "Maximum number of channels a user can join",
581 },
582 {
583 "max_chans_per_user_large",
584 OUTPUT_DECIMAL,
585 &ConfigChannel.max_chans_per_user_large,
586 "Maximum extended number of channels a user can join",
587 },
588 {
589 "no_create_on_split",
590 OUTPUT_BOOLEAN_YN,
591 &ConfigChannel.no_create_on_split,
592 "Disallow creation of channels when split",
593 },
594 {
595 "no_join_on_split",
596 OUTPUT_BOOLEAN_YN,
597 &ConfigChannel.no_join_on_split,
598 "Disallow joining channels when split",
599 },
600 {
601 "only_ascii_channels",
602 OUTPUT_BOOLEAN_YN,
603 &ConfigChannel.only_ascii_channels,
604 "Controls whether non-ASCII is disabled for JOIN"
605 },
606 {
607 "use_except",
608 OUTPUT_BOOLEAN_YN,
609 &ConfigChannel.use_except,
610 "Enable chanmode +e (ban exceptions)",
611 },
612 {
613 "use_invex",
614 OUTPUT_BOOLEAN_YN,
615 &ConfigChannel.use_invex,
616 "Enable chanmode +I (invite exceptions)",
617 },
618 {
619 "use_forward",
620 OUTPUT_BOOLEAN_YN,
621 &ConfigChannel.use_forward,
622 "Enable chanmode +f (channel forwarding)",
623 },
624 {
625 "use_knock",
626 OUTPUT_BOOLEAN_YN,
627 &ConfigChannel.use_knock,
628 "Enable /KNOCK",
629 },
630 {
631 "resv_forcepart",
632 OUTPUT_BOOLEAN_YN,
633 &ConfigChannel.resv_forcepart,
634 "Force-part local users on channel RESV"
635 },
636 {
637 "disable_hidden",
638 OUTPUT_BOOLEAN_YN,
639 &ConfigServerHide.disable_hidden,
640 "Prevent servers from hiding themselves from a flattened /links",
641 },
642 {
643 "flatten_links",
644 OUTPUT_BOOLEAN_YN,
645 &ConfigServerHide.flatten_links,
646 "Flatten /links list",
647 },
648 {
649 "hidden",
650 OUTPUT_BOOLEAN_YN,
651 &ConfigServerHide.hidden,
652 "Hide this server from a flattened /links on remote servers",
653 },
654 {
655 "links_delay",
656 OUTPUT_DECIMAL,
657 &ConfigServerHide.links_delay,
658 "Links rehash delay"
659 },
660 /* --[ END OF TABLE ]---------------------------------------------- */
661 { (char *) 0, (unsigned int) 0, (void *) 0, (char *) 0}
662 };
663 /* *INDENT-ON* */
664
665 /*
666 ** m_info
667 ** parv[1] = servername
668 */
669 static void
670 m_info(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
671 {
672 static time_t last_used = 0L;
673
674 if((last_used + ConfigFileEntry.pace_wait) > rb_current_time())
675 {
676 /* safe enough to give this on a local connect only */
677 sendto_one(source_p, form_str(RPL_LOAD2HI),
678 me.name, source_p->name, "INFO");
679 sendto_one_numeric(source_p, RPL_ENDOFINFO, form_str(RPL_ENDOFINFO));
680 return;
681 }
682 else
683 last_used = rb_current_time();
684
685 if(hunt_server(client_p, source_p, ":%s INFO :%s", 1, parc, parv) != HUNTED_ISME)
686 return;
687
688 info_spy(source_p);
689
690 send_info_text(source_p);
691 send_birthdate_online_time(source_p);
692
693 sendto_one_numeric(source_p, RPL_ENDOFINFO, form_str(RPL_ENDOFINFO));
694 }
695
696 /*
697 ** mo_info
698 ** parv[1] = servername
699 */
700 static void
701 mo_info(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
702 {
703 if(hunt_server(client_p, source_p, ":%s INFO :%s", 1, parc, parv) == HUNTED_ISME)
704 {
705 info_spy(source_p);
706 send_info_text(source_p);
707
708 if(IsOper(source_p))
709 {
710 send_conf_options(source_p);
711 sendto_one_numeric(source_p, RPL_INFO, ":%s",
712 rb_lib_version());
713 }
714
715 send_birthdate_online_time(source_p);
716
717 sendto_one_numeric(source_p, RPL_ENDOFINFO, form_str(RPL_ENDOFINFO));
718 }
719 }
720
721 /*
722 * send_info_text
723 *
724 * inputs - client pointer to send info text to
725 * output - none
726 * side effects - info text is sent to client
727 */
728 static void
729 send_info_text(struct Client *source_p)
730 {
731 const char **text = infotext;
732
733 while (*text)
734 {
735 sendto_one_numeric(source_p, RPL_INFO, form_str(RPL_INFO), *text++);
736 }
737
738 sendto_one_numeric(source_p, RPL_INFO, form_str(RPL_INFO), "");
739 }
740
741 /*
742 * send_birthdate_online_time
743 *
744 * inputs - client pointer to send to
745 * output - none
746 * side effects - birthdate and online time are sent
747 */
748 static void
749 send_birthdate_online_time(struct Client *source_p)
750 {
751 char tbuf[26]; /* this needs to be 26 - see ctime_r manpage */
752 sendto_one(source_p, ":%s %d %s :Birth Date: %s, compile # %s",
753 get_id(&me, source_p), RPL_INFO,
754 get_id(source_p, source_p), creation, generation);
755
756 sendto_one(source_p, ":%s %d %s :On-line since %s",
757 get_id(&me, source_p), RPL_INFO,
758 get_id(source_p, source_p), rb_ctime(startup_time, tbuf, sizeof(tbuf)));
759 }
760
761 /*
762 * send_conf_options
763 *
764 * inputs - client pointer to send to
765 * output - none
766 * side effects - send config options to client
767 */
768 static void
769 send_conf_options(struct Client *source_p)
770 {
771 Info *infoptr;
772 int i = 0;
773
774 /*
775 * Now send them a list of all our configuration options
776 * (mostly from defaults.h)
777 */
778 for (infoptr = MyInformation; infoptr->name; infoptr++)
779 {
780 if(infoptr->intvalue)
781 {
782 sendto_one(source_p, ":%s %d %s :%-30s %-16d [%s]",
783 get_id(&me, source_p), RPL_INFO,
784 get_id(source_p, source_p),
785 infoptr->name, infoptr->intvalue,
786 infoptr->desc);
787 }
788 else
789 {
790 sendto_one(source_p, ":%s %d %s :%-30s %-16s [%s]",
791 get_id(&me, source_p), RPL_INFO,
792 get_id(source_p, source_p),
793 infoptr->name, infoptr->strvalue,
794 infoptr->desc);
795 }
796 }
797
798 /*
799 * Parse the info_table[] and do the magic.
800 */
801 for (i = 0; info_table[i].name; i++)
802 {
803 switch (info_table[i].output_type)
804 {
805 /*
806 * For "char *" references
807 */
808 case OUTPUT_STRING:
809 {
810 char *option = *((char **) info_table[i].option);
811
812 sendto_one(source_p, ":%s %d %s :%-30s %-16s [%s]",
813 get_id(&me, source_p), RPL_INFO,
814 get_id(source_p, source_p),
815 info_table[i].name,
816 option ? option : "NONE",
817 info_table[i].desc ? info_table[i].desc : "<none>");
818
819 break;
820 }
821 /*
822 * For "char foo[]" references
823 */
824 case OUTPUT_STRING_PTR:
825 {
826 char *option = (char *) info_table[i].option;
827
828 sendto_one(source_p, ":%s %d %s :%-30s %-16s [%s]",
829 get_id(&me, source_p), RPL_INFO,
830 get_id(source_p, source_p),
831 info_table[i].name,
832 EmptyString(option) ? "NONE" : option,
833 info_table[i].desc ? info_table[i].desc : "<none>");
834
835 break;
836 }
837 /*
838 * Output info_table[i].option as a decimal value.
839 */
840 case OUTPUT_DECIMAL:
841 {
842 int option = *((int *) info_table[i].option);
843
844 sendto_one(source_p, ":%s %d %s :%-30s %-16d [%s]",
845 get_id(&me, source_p), RPL_INFO,
846 get_id(source_p, source_p),
847 info_table[i].name,
848 option,
849 info_table[i].desc ? info_table[i].desc : "<none>");
850
851 break;
852 }
853
854 /*
855 * Output info_table[i].option as "ON" or "OFF"
856 */
857 case OUTPUT_BOOLEAN:
858 {
859 int option = *((int *) info_table[i].option);
860
861 sendto_one(source_p, ":%s %d %s :%-30s %-16s [%s]",
862 get_id(&me, source_p), RPL_INFO,
863 get_id(source_p, source_p),
864 info_table[i].name,
865 option ? "ON" : "OFF",
866 info_table[i].desc ? info_table[i].desc : "<none>");
867
868 break;
869 }
870 /*
871 * Output info_table[i].option as "YES" or "NO"
872 */
873 case OUTPUT_BOOLEAN_YN:
874 {
875 int option = *((int *) info_table[i].option);
876
877 sendto_one(source_p, ":%s %d %s :%-30s %-16s [%s]",
878 get_id(&me, source_p), RPL_INFO,
879 get_id(source_p, source_p),
880 info_table[i].name,
881 option ? "YES" : "NO",
882 info_table[i].desc ? info_table[i].desc : "<none>");
883
884 break;
885 }
886
887 case OUTPUT_BOOLEAN2:
888 {
889 int option = *((int *) info_table[i].option);
890
891 sendto_one(source_p, ":%s %d %s :%-30s %-16s [%s]",
892 me.name, RPL_INFO, source_p->name,
893 info_table[i].name,
894 option ? ((option == 1) ? "MASK" : "YES") : "NO",
895 info_table[i].desc ? info_table[i].desc : "<none>");
896 } /* switch (info_table[i].output_type) */
897 }
898 } /* forloop */
899
900
901 /* Don't send oper_only_umodes...it's a bit mask, we will have to decode it
902 ** in order for it to show up properly to opers who issue INFO
903 */
904
905 sendto_one_numeric(source_p, RPL_INFO, form_str(RPL_INFO), "");
906 }
907
908 /* info_spy()
909 *
910 * input - pointer to client
911 * output - none
912 * side effects - hook doing_info is called
913 */
914 static void
915 info_spy(struct Client *source_p)
916 {
917 hook_data hd;
918
919 hd.client = source_p;
920 hd.arg1 = hd.arg2 = NULL;
921
922 call_hook(doing_info_hook, &hd);
923 }