ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/modules/m_info.c
Revision: 1309
Committed: Sun Mar 25 11:24:18 2012 UTC (13 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/modules/m_info.c
File size: 19233 byte(s)
Log Message:
- renaming files:

  ircd_parser.y -> conf_parser.y
  ircd_lexer.l  -> conf_lexer.l
  s_conf.c      -> conf.c
  s_conf.h      -> conf.h
  s_log.c       -> log.c
  s_log.h       -> log.h

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * m_info.c: Sends information about the server.
4 *
5 * Copyright (C) 2005 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #include "list.h"
27 #include "m_info.h"
28 #include "channel.h"
29 #include "client.h"
30 #include "irc_string.h"
31 #include "ircd.h"
32 #include "numeric.h"
33 #include "s_serv.h"
34 #include "s_user.h"
35 #include "send.h"
36 #include "conf.h"
37 #include "parse.h"
38 #include "modules.h"
39
40
41 static void send_conf_options(struct Client *);
42 static void send_birthdate_online_time(struct Client *);
43 static void send_info_text(struct Client *);
44
45 /*
46 * jdc -- Structure for our configuration value table
47 */
48 struct InfoStruct
49 {
50 const char *name; /* Displayed variable name */
51 unsigned int output_type; /* See below #defines */
52 void *option; /* Pointer reference to the value */
53 const char *desc; /* ASCII description of the variable */
54 };
55
56 /* Types for output_type in InfoStruct */
57 #define OUTPUT_STRING 0x0001 /* Output option as %s w/ dereference */
58 #define OUTPUT_STRING_PTR 0x0002 /* Output option as %s w/out deference */
59 #define OUTPUT_DECIMAL 0x0004 /* Output option as decimal (%d) */
60 #define OUTPUT_BOOLEAN 0x0008 /* Output option as "ON" or "OFF" */
61 #define OUTPUT_BOOLEAN_YN 0x0010 /* Output option as "YES" or "NO" */
62 #define OUTPUT_BOOLEAN2 0x0020 /* Output option as "YES/NO/MASKED" */
63
64 static const struct InfoStruct info_table[] =
65 {
66 /* --[ START OF TABLE ]-------------------------------------------- */
67 {
68 "network_name",
69 OUTPUT_STRING,
70 &ServerInfo.network_name,
71 "Network name"
72 },
73 {
74 "network_desc",
75 OUTPUT_STRING,
76 &ServerInfo.network_desc,
77 "Network description"
78 },
79 {
80 "hub",
81 OUTPUT_BOOLEAN_YN,
82 &ServerInfo.hub,
83 "Server is a hub"
84 },
85 {
86 "use_logging",
87 OUTPUT_BOOLEAN_YN,
88 &ConfigLoggingEntry.use_logging,
89 "Enable logging"
90 },
91 {
92 "restrict_channels",
93 OUTPUT_BOOLEAN_YN,
94 &ConfigChannel.restrict_channels,
95 "Only reserved channels are allowed"
96 },
97 {
98 "disable_local_channels",
99 OUTPUT_BOOLEAN_YN,
100 &ConfigChannel.disable_local_channels,
101 "Prevent users from joining &channels"
102 },
103 {
104 "use_invex",
105 OUTPUT_BOOLEAN_YN,
106 &ConfigChannel.use_invex,
107 "Enable chanmode +I (invite exceptions)"
108 },
109 {
110 "use_except",
111 OUTPUT_BOOLEAN_YN,
112 &ConfigChannel.use_except,
113 "Enable chanmode +e (ban exceptions)"
114 },
115 {
116 "use_knock",
117 OUTPUT_BOOLEAN_YN,
118 &ConfigChannel.use_knock,
119 "Enable /KNOCK"
120 },
121 {
122 "knock_delay",
123 OUTPUT_DECIMAL,
124 &ConfigChannel.knock_delay,
125 "Delay between a users KNOCK attempts"
126 },
127 {
128 "knock_delay_channel",
129 OUTPUT_DECIMAL,
130 &ConfigChannel.knock_delay_channel,
131 "Delay between KNOCK attempts to a channel"
132 },
133 {
134 "max_chans_per_user",
135 OUTPUT_DECIMAL,
136 &ConfigChannel.max_chans_per_user,
137 "Maximum number of channels a user can join"
138 },
139 {
140 "quiet_on_ban",
141 OUTPUT_BOOLEAN_YN,
142 &ConfigChannel.quiet_on_ban,
143 "Banned users may not send text to a channel"
144 },
145 {
146 "max_bans",
147 OUTPUT_DECIMAL,
148 &ConfigChannel.max_bans,
149 "Total +b/e/I modes allowed in a channel"
150 },
151 {
152 "default_split_user_count",
153 OUTPUT_DECIMAL,
154 &ConfigChannel.default_split_user_count,
155 "Startup value of SPLITUSERS"
156 },
157 {
158 "default_split_server_count",
159 OUTPUT_DECIMAL,
160 &ConfigChannel.default_split_server_count,
161 "Startup value of SPLITNUM"
162 },
163 {
164 "no_create_on_split",
165 OUTPUT_BOOLEAN_YN,
166 &ConfigChannel.no_create_on_split,
167 "Disallow creation of channels when split"
168 },
169 {
170 "no_join_on_split",
171 OUTPUT_BOOLEAN_YN,
172 &ConfigChannel.no_join_on_split,
173 "Disallow joining channels when split"
174 },
175 {
176 "burst_topicwho",
177 OUTPUT_BOOLEAN_YN,
178 &ConfigChannel.burst_topicwho,
179 "Enable sending of who set topic on topicburst"
180 },
181 {
182 "flatten_links",
183 OUTPUT_BOOLEAN_YN,
184 &ConfigServerHide.flatten_links,
185 "Flatten /links list"
186 },
187 {
188 "links_delay",
189 OUTPUT_DECIMAL,
190 &ConfigServerHide.links_delay,
191 "Links rehash delay"
192 },
193 {
194 "hidden",
195 OUTPUT_BOOLEAN_YN,
196 &ConfigServerHide.hidden,
197 "Hide this server from a flattened /links on remote servers"
198 },
199 {
200 "disable_hidden",
201 OUTPUT_BOOLEAN_YN,
202 &ConfigServerHide.disable_hidden,
203 "Prevent servers from hiding themselves from a flattened /links"
204 },
205 {
206 "hide_servers",
207 OUTPUT_BOOLEAN_YN,
208 &ConfigServerHide.hide_servers,
209 "Hide servernames from users"
210 },
211 {
212 "hidden_name",
213 OUTPUT_STRING,
214 &ConfigServerHide.hidden_name,
215 "Server name users see if hide_servers = yes"
216 },
217 {
218 "hide_server_ips",
219 OUTPUT_BOOLEAN_YN,
220 &ConfigServerHide.hide_server_ips,
221 "Prevent people from seeing server IPs"
222 },
223 {
224 "gline_min_cidr",
225 OUTPUT_DECIMAL,
226 &ConfigFileEntry.gline_min_cidr,
227 "Minimum required length of a CIDR bitmask for IPv4 G-Lines"
228 },
229 {
230 "gline_min_cidr6",
231 OUTPUT_DECIMAL,
232 &ConfigFileEntry.gline_min_cidr6,
233 "Minimum required length of a CIDR bitmask for IPv6 G-Lines"
234 },
235 {
236 "invisible_on_connect",
237 OUTPUT_BOOLEAN_YN,
238 &ConfigFileEntry.invisible_on_connect,
239 "Automatically set mode +i on connecting users"
240 },
241 {
242 "burst_away",
243 OUTPUT_BOOLEAN_YN,
244 &ConfigFileEntry.burst_away,
245 "Send /away string that users have set on the server burst"
246 },
247 {
248 "use_whois_actually",
249 OUTPUT_BOOLEAN_YN,
250 &ConfigFileEntry.use_whois_actually,
251 "Show IP address on /WHOIS when possible"
252 },
253 {
254 "kill_chase_time_limit",
255 OUTPUT_DECIMAL,
256 &ConfigFileEntry.kill_chase_time_limit,
257 "Nick Change Tracker for KILL"
258 },
259 {
260 "hide_spoof_ips",
261 OUTPUT_BOOLEAN_YN,
262 &ConfigFileEntry.hide_spoof_ips,
263 "Hide spoofed IP's"
264 },
265 {
266 "ignore_bogus_ts",
267 OUTPUT_BOOLEAN_YN,
268 &ConfigFileEntry.ignore_bogus_ts,
269 "Ignore bogus timestamps from other servers"
270 },
271 {
272 "disable_auth",
273 OUTPUT_BOOLEAN_YN,
274 &ConfigFileEntry.disable_auth,
275 "Completely disable ident lookups"
276 },
277 {
278 "disable_remote_commands",
279 OUTPUT_BOOLEAN_YN,
280 &ConfigFileEntry.disable_remote,
281 "Prevent users issuing commands on remote servers"
282 },
283 {
284 "tkline_expire_notices",
285 OUTPUT_BOOLEAN_YN,
286 &ConfigFileEntry.tkline_expire_notices,
287 "Show temporary kline/xline expire notices"
288 },
289 {
290 "default_floodcount",
291 OUTPUT_DECIMAL,
292 &ConfigFileEntry.default_floodcount,
293 "Startup value of FLOODCOUNT"
294 },
295 {
296 "failed_oper_notice",
297 OUTPUT_BOOLEAN,
298 &ConfigFileEntry.failed_oper_notice,
299 "Inform opers if someone /oper's with the wrong password"
300 },
301 {
302 "dots_in_ident",
303 OUTPUT_DECIMAL,
304 &ConfigFileEntry.dots_in_ident,
305 "Number of permissable dots in an ident"
306 },
307 {
308 "min_nonwildcard",
309 OUTPUT_DECIMAL,
310 &ConfigFileEntry.min_nonwildcard,
311 "Minimum non-wildcard chars in K/G lines"
312 },
313 {
314 "min_nonwildcard_simple",
315 OUTPUT_DECIMAL,
316 &ConfigFileEntry.min_nonwildcard_simple,
317 "Minimum non-wildcards in gecos bans"
318 },
319 {
320 "max_accept",
321 OUTPUT_DECIMAL,
322 &ConfigFileEntry.max_accept,
323 "Maximum nicknames on accept list"
324 },
325 {
326 "anti_nick_flood",
327 OUTPUT_BOOLEAN,
328 &ConfigFileEntry.anti_nick_flood,
329 "NICK flood protection"
330 },
331 {
332 "max_nick_time",
333 OUTPUT_DECIMAL,
334 &ConfigFileEntry.max_nick_time,
335 "NICK flood protection time interval"
336 },
337 {
338 "max_nick_changes",
339 OUTPUT_DECIMAL,
340 &ConfigFileEntry.max_nick_changes,
341 "NICK change threshhold setting"
342 },
343 {
344 "anti_spam_exit_message_time",
345 OUTPUT_DECIMAL,
346 &ConfigFileEntry.anti_spam_exit_message_time,
347 "Duration a client must be connected for to have an exit message"
348 },
349 {
350 "ts_warn_delta",
351 OUTPUT_DECIMAL,
352 &ConfigFileEntry.ts_warn_delta,
353 "Maximum permitted TS delta before displaying a warning"
354 },
355 {
356 "ts_max_delta",
357 OUTPUT_DECIMAL,
358 &ConfigFileEntry.ts_max_delta,
359 "Maximum permitted TS delta from another server"
360 },
361 {
362 "kline_with_reason",
363 OUTPUT_BOOLEAN_YN,
364 &ConfigFileEntry.kline_with_reason,
365 "Display K-line reason to client on disconnect"
366 },
367 {
368 "kline_reason",
369 OUTPUT_STRING,
370 &ConfigFileEntry.kline_reason,
371 "Reason given to K-lined clients on sign off"
372 },
373 {
374 "warn_no_nline",
375 OUTPUT_BOOLEAN,
376 &ConfigFileEntry.warn_no_nline,
377 "Display warning if connecting server lacks N-line"
378 },
379 {
380 "stats_o_oper_only",
381 OUTPUT_BOOLEAN_YN,
382 &ConfigFileEntry.stats_o_oper_only,
383 "STATS O output is only shown to operators"
384 },
385 {
386 "stats_P_oper_only",
387 OUTPUT_BOOLEAN_YN,
388 &ConfigFileEntry.stats_P_oper_only,
389 "STATS P is only shown to operators"
390 },
391 {
392 "stats_i_oper_only",
393 OUTPUT_BOOLEAN2,
394 &ConfigFileEntry.stats_i_oper_only,
395 "STATS I output is only shown to operators"
396 },
397 {
398 "stats_k_oper_only",
399 OUTPUT_BOOLEAN2,
400 &ConfigFileEntry.stats_k_oper_only,
401 "STATS K output is only shown to operators"
402 },
403 {
404 "caller_id_wait",
405 OUTPUT_DECIMAL,
406 &ConfigFileEntry.caller_id_wait,
407 "Minimum delay between notifying UMODE +g users of messages"
408 },
409 {
410 "opers_bypass_callerid",
411 OUTPUT_BOOLEAN_YN,
412 &ConfigFileEntry.opers_bypass_callerid,
413 "Allows IRC operators to message users who are +g (callerid)"
414 },
415 {
416 "pace_wait_simple",
417 OUTPUT_DECIMAL,
418 &ConfigFileEntry.pace_wait_simple,
419 "Minimum delay between less intensive commands"
420 },
421 {
422 "pace_wait",
423 OUTPUT_DECIMAL,
424 &ConfigFileEntry.pace_wait,
425 "Minimum delay between uses of certain commands"
426 },
427 {
428 "short_motd",
429 OUTPUT_BOOLEAN_YN,
430 &ConfigFileEntry.short_motd,
431 "Do not show MOTD; only tell clients they should read it"
432 },
433 {
434 "ping_cookie",
435 OUTPUT_BOOLEAN,
436 &ConfigFileEntry.ping_cookie,
437 "Require ping cookies to connect"
438 },
439 {
440 "no_oper_flood",
441 OUTPUT_BOOLEAN,
442 &ConfigFileEntry.no_oper_flood,
443 "Reduce flood control for operators"
444 },
445 {
446 "true_no_oper_flood",
447 OUTPUT_BOOLEAN,
448 &ConfigFileEntry.true_no_oper_flood,
449 "Completely disable flood control for operators"
450 },
451 {
452 "oper_pass_resv",
453 OUTPUT_BOOLEAN_YN,
454 &ConfigFileEntry.oper_pass_resv,
455 "Opers can over-ride RESVs"
456 },
457 {
458 "max_targets",
459 OUTPUT_DECIMAL,
460 &ConfigFileEntry.max_targets,
461 "The maximum number of PRIVMSG/NOTICE targets"
462 },
463 {
464 "client_flood",
465 OUTPUT_DECIMAL,
466 &ConfigFileEntry.client_flood,
467 "Maximum amount of data in a client's queue before they are disconnected"
468 },
469 {
470 "throttle_time",
471 OUTPUT_DECIMAL,
472 &ConfigFileEntry.throttle_time,
473 "Minimum time between client reconnects"
474 },
475 {
476 "glines",
477 OUTPUT_BOOLEAN,
478 &ConfigFileEntry.glines,
479 "G-line (network-wide K-line) support"
480 },
481 {
482 "duration",
483 OUTPUT_DECIMAL,
484 &ConfigFileEntry.gline_time,
485 "Expiry time for G-lines"
486 },
487 /* --[ END OF TABLE ]---------------------------------------------- */
488 {
489 NULL,
490 0,
491 NULL,
492 0
493 }
494 };
495
496 /*
497 ** m_info()
498 ** parv[0] = sender prefix
499 ** parv[1] = servername
500 */
501 static void
502 m_info(struct Client *client_p, struct Client *source_p,
503 int parc, char *parv[])
504 {
505 static time_t last_used = 0;
506
507 if ((last_used + ConfigFileEntry.pace_wait) > CurrentTime)
508 {
509 /* safe enough to give this on a local connect only */
510 sendto_one(source_p, form_str(RPL_LOAD2HI),
511 me.name, source_p->name);
512 return;
513 }
514
515 last_used = CurrentTime;
516
517 if (!ConfigFileEntry.disable_remote)
518 if (hunt_server(client_p,source_p, ":%s INFO :%s", 1,
519 parc, parv) != HUNTED_ISME)
520 return;
521
522 send_info_text(source_p);
523 }
524
525 /*
526 ** mo_info()
527 ** parv[0] = sender prefix
528 ** parv[1] = servername
529 */
530 static void
531 mo_info(struct Client *client_p, struct Client *source_p,
532 int parc, char *parv[])
533 {
534 if (hunt_server(client_p, source_p, ":%s INFO :%s", 1,
535 parc, parv) != HUNTED_ISME)
536 return;
537
538 send_info_text(source_p);
539 }
540
541 /*
542 ** ms_info()
543 ** parv[0] = sender prefix
544 ** parv[1] = servername
545 */
546 static void
547 ms_info(struct Client *client_p, struct Client *source_p,
548 int parc, char *parv[])
549 {
550 if (!IsClient(source_p))
551 return;
552
553 if (hunt_server(client_p, source_p, ":%s INFO :%s", 1,
554 parc, parv) != HUNTED_ISME)
555 return;
556
557 send_info_text(source_p);
558 }
559
560 /* send_info_text()
561 *
562 * inputs - client pointer to send info text to
563 * output - NONE
564 * side effects - info text is sent to client
565 */
566 static void
567 send_info_text(struct Client *source_p)
568 {
569 const char **text = infotext;
570 char *source, *target;
571
572 sendto_realops_flags(UMODE_SPY, L_ALL,
573 "INFO requested by %s (%s@%s) [%s]",
574 source_p->name, source_p->username,
575 source_p->host, source_p->servptr->name);
576
577 if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) &&
578 HasID(source_p))
579 source = me.id, target = source_p->id;
580 else
581 source = me.name, target = source_p->name;
582
583 while (*text)
584 {
585 const char *line = *text++;
586
587 if (*line == '\0')
588 line = " ";
589
590 sendto_one(source_p, form_str(RPL_INFO),
591 source, target, line);
592 }
593
594 if (HasUMode(source_p, UMODE_OPER))
595 send_conf_options(source_p);
596
597 send_birthdate_online_time(source_p);
598
599 sendto_one(source_p, form_str(RPL_ENDOFINFO),
600 me.name, source_p->name);
601 }
602
603 /* send_birthdate_online_time()
604 *
605 * inputs - client pointer to send to
606 * output - NONE
607 * side effects - birthdate and online time are sent
608 */
609 static void
610 send_birthdate_online_time(struct Client *source_p)
611 {
612 if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
613 {
614 sendto_one(source_p, ":%s %d %s :On-line since %s",
615 me.id, RPL_INFO, source_p->id,
616 myctime(me.localClient->firsttime));
617 }
618 else
619 {
620 sendto_one(source_p, ":%s %d %s :On-line since %s",
621 me.name, RPL_INFO, source_p->name,
622 myctime(me.localClient->firsttime));
623 }
624 }
625
626 /* send_conf_options()
627 *
628 * inputs - client pointer to send to
629 * output - NONE
630 * side effects - send config options to client
631 */
632 static void
633 send_conf_options(struct Client *source_p)
634 {
635 Info *infoptr;
636 const char *from, *to;
637 const struct InfoStruct *iptr = NULL;
638
639 /* Now send them a list of all our configuration options
640 * (mostly from defaults.h and config.h)
641 */
642 if (!MyClient(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
643 {
644 from = me.id;
645 to = source_p->id;
646 }
647 else
648 {
649 from = me.name;
650 to = source_p->name;
651 }
652
653 for (infoptr = MyInformation; infoptr->name; infoptr++)
654 {
655 if (infoptr->intvalue)
656 {
657 sendto_one(source_p, ":%s %d %s :%-30s %-5d [%-30s]",
658 from, RPL_INFO, to, infoptr->name,
659 infoptr->intvalue, infoptr->desc);
660 }
661 else
662 {
663 sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
664 from, RPL_INFO, to, infoptr->name,
665 infoptr->strvalue, infoptr->desc);
666 }
667 }
668
669 /*
670 * Parse the info_table[] and do the magic.
671 */
672 for (iptr = info_table; iptr->name; ++iptr)
673 {
674 switch (iptr->output_type)
675 {
676 /* For "char *" references */
677 case OUTPUT_STRING:
678 {
679 const char *option = *((char **)iptr->option);
680
681 sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
682 from, RPL_INFO, to,
683 iptr->name, option ? option : "NONE",
684 iptr->desc ? iptr->desc : "<none>");
685 break;
686 }
687
688 /* For "char foo[]" references */
689 case OUTPUT_STRING_PTR:
690 {
691 const char *option = iptr->option;
692
693 sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
694 from, RPL_INFO, to,
695 iptr->name, option ? option : "NONE",
696 iptr->desc ? iptr->desc : "<none>");
697 break;
698 }
699
700 /* Output info_table[i].option as a decimal value. */
701 case OUTPUT_DECIMAL:
702 {
703 const int option = *((int *)iptr->option);
704
705 sendto_one(source_p, ":%s %d %s :%-30s %-5d [%-30s]",
706 from, RPL_INFO, to, iptr->name,
707 option, iptr->desc ? iptr->desc : "<none>");
708 break;
709 }
710
711 /* Output info_table[i].option as "ON" or "OFF" */
712 case OUTPUT_BOOLEAN:
713 {
714 const int option = *((int *)iptr->option);
715
716 sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
717 from, RPL_INFO, to,
718 iptr->name, option ? "ON" : "OFF",
719 iptr->desc ? iptr->desc : "<none>");
720
721 break;
722 }
723
724 /* Output info_table[i].option as "YES" or "NO" */
725 case OUTPUT_BOOLEAN_YN:
726 {
727 int option = *((int *)iptr->option);
728
729 sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
730 from, RPL_INFO, to,
731 iptr->name, option ? "YES" : "NO",
732 iptr->desc ? iptr->desc : "<none>");
733 break;
734 }
735
736 case OUTPUT_BOOLEAN2:
737 {
738 int option = *((int *)iptr->option);
739
740 sendto_one(source_p, ":%s %d %s :%-30s %-5s [%-30s]",
741 from, RPL_INFO, to,
742 iptr->name, option ? ((option == 1) ? "MASK" : "YES") : "NO",
743 iptr->desc ? iptr->desc : "<none>");
744 break;
745 }
746 }
747 }
748
749 /* Don't send oper_only_umodes...it's a bit mask, we will have to decode it
750 * in order for it to show up properly to opers who issue INFO
751 */
752 #ifndef EFNET
753 /* jdc -- Only send compile information to admins. */
754 if (HasUMode(source_p, UMODE_ADMIN))
755 sendto_one(source_p, ":%s %d %s :Running on [%s]",
756 from, RPL_INFO, to, ircd_platform);
757 #endif
758 sendto_one(source_p, form_str(RPL_INFO),
759 from, to, "");
760 }
761
762 static struct Message info_msgtab = {
763 "INFO", 0, 0, 0, MAXPARA, MFLG_SLOW, 0,
764 { m_unregistered, m_info, ms_info, m_ignore, mo_info, m_ignore }
765 };
766
767 static void
768 module_init(void)
769 {
770 mod_add_cmd(&info_msgtab);
771 }
772
773 static void
774 module_exit(void)
775 {
776 mod_del_cmd(&info_msgtab);
777 }
778
779 struct module module_entry = {
780 .node = { NULL, NULL, NULL },
781 .name = NULL,
782 .version = "$Revision$",
783 .handle = NULL,
784 .modinit = module_init,
785 .modexit = module_exit,
786 .flags = 0
787 };

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision