ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/src/modules.c
Revision: 908
Committed: Sun Nov 4 23:21:51 2007 UTC (16 years, 4 months ago) by stu
Content type: text/x-csrc
Original Path: ircd-hybrid-7.2/src/modules.c
File size: 17364 byte(s)
Log Message:
Completely redo the build system.  Now uses libtool and automake.  Suggest you clean out your tree and then do ./autogen.sh.

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * modules.c: A module loader.
4     *
5     * Copyright (C) 2002 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 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26     #include "tools.h"
27     #include "modules.h"
28     #include "s_log.h"
29     #include "ircd.h"
30     #include "client.h"
31     #include "send.h"
32     #include "s_conf.h"
33     #include "handlers.h"
34     #include "numeric.h"
35     #include "parse.h"
36     #include "ircd_defs.h"
37     #include "irc_string.h"
38     #include "memory.h"
39     #include "list.h"
40    
41 stu 908 #define SHARED_SUFFIX "so"
42    
43 adx 30 /* -TimeMr14C:
44     * I have moved the dl* function definitions and
45     * the two functions (load_a_module / unload_a_module) to the
46     * file dynlink.c
47     * And also made the necessary changes to those functions
48     * to comply with shl_load and friends.
49     * In this file, to keep consistency with the makefile,
50     * I added the ability to load *.sl files, too.
51     * 27/02/2002
52     */
53    
54     #ifndef STATIC_MODULES
55    
56     dlink_list mod_list = { NULL, NULL, 0 };
57    
58     static const char *core_module_table[] =
59     {
60     "m_die",
61     "m_join",
62     "m_kick",
63     "m_kill",
64     "m_message",
65     "m_mode",
66     "m_nick",
67     "m_part",
68     "m_quit",
69     "m_server",
70     "m_sjoin",
71     "m_squit",
72     NULL
73     };
74    
75     static dlink_list mod_paths = { NULL, NULL, 0 };
76     static dlink_list conf_modules = { NULL, NULL, 0 };
77    
78     static void mo_modload(struct Client *, struct Client *, int, char *[]);
79     static void mo_modlist(struct Client *, struct Client *, int, char *[]);
80     static void mo_modreload(struct Client *, struct Client *, int, char *[]);
81     static void mo_modunload(struct Client *, struct Client *, int, char *[]);
82     static void mo_modrestart(struct Client *, struct Client *, int, char *[]);
83    
84     struct Message modload_msgtab = {
85     "MODLOAD", 0, 0, 2, 0, MFLG_SLOW, 0,
86     {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modload, m_ignore}
87     };
88    
89     struct Message modunload_msgtab = {
90     "MODUNLOAD", 0, 0, 2, 0, MFLG_SLOW, 0,
91     {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modunload, m_ignore}
92     };
93    
94     struct Message modreload_msgtab = {
95     "MODRELOAD", 0, 0, 2, 0, MFLG_SLOW, 0,
96     {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modreload, m_ignore}
97     };
98    
99     struct Message modlist_msgtab = {
100     "MODLIST", 0, 0, 0, 0, MFLG_SLOW, 0,
101     {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modlist, m_ignore}
102     };
103    
104     struct Message modrestart_msgtab = {
105     "MODRESTART", 0, 0, 0, 0, MFLG_SLOW, 0,
106     {m_unregistered, m_not_oper, m_ignore, m_ignore, mo_modrestart, m_ignore}
107     };
108    
109    
110     extern struct Message error_msgtab;
111    
112     /*
113     * modules_init
114     *
115     * input - NONE
116     * output - NONE
117     * side effects - The basic module manipulation modules are loaded
118     */
119     void
120     modules_init(void)
121     {
122     mod_add_cmd(&modload_msgtab);
123     mod_add_cmd(&modunload_msgtab);
124     mod_add_cmd(&modreload_msgtab);
125     mod_add_cmd(&modlist_msgtab);
126     mod_add_cmd(&modrestart_msgtab);
127     mod_add_cmd(&error_msgtab);
128     }
129    
130     /* mod_find_path()
131     *
132     * input - path
133     * output - none
134     * side effects - returns a module path from path
135     */
136     static struct module_path *
137     mod_find_path(const char *path)
138     {
139     dlink_node *ptr;
140     struct module_path *mpath;
141    
142     DLINK_FOREACH(ptr, mod_paths.head)
143     {
144     mpath = ptr->data;
145    
146     if (!strcmp(path, mpath->path))
147     return mpath;
148     }
149    
150     return NULL;
151     }
152    
153     /* mod_add_path()
154     *
155     * input - path
156     * output - NONE
157     * side effects - adds path to list
158     */
159     void
160     mod_add_path(const char *path)
161     {
162     struct module_path *pathst;
163    
164     if (mod_find_path(path))
165     return;
166    
167     pathst = MyMalloc(sizeof(struct module_path));
168    
169     strlcpy(pathst->path, path, sizeof(pathst->path));
170     dlinkAdd(pathst, &pathst->node, &mod_paths);
171     }
172    
173     /* add_conf_module
174     *
175     * input - module name
176     * output - NONE
177     * side effects - adds module to conf_mod
178     */
179     void
180     add_conf_module(const char *name)
181     {
182     struct module_path *pathst;
183    
184     pathst = MyMalloc(sizeof(struct module_path));
185    
186     strlcpy(pathst->path, name, sizeof(pathst->path));
187     dlinkAdd(pathst, &pathst->node, &conf_modules);
188     }
189    
190     /* mod_clear_paths()
191     *
192     * input - NONE
193     * output - NONE
194     * side effects - clear the lists of paths and conf modules
195     */
196     void
197     mod_clear_paths(void)
198     {
199     struct module_path *pathst;
200     dlink_node *ptr;
201     dlink_node *next_ptr;
202    
203     DLINK_FOREACH_SAFE(ptr, next_ptr, mod_paths.head)
204     {
205     pathst = ptr->data;
206    
207     dlinkDelete(&pathst->node, &mod_paths);
208     MyFree(pathst);
209     }
210    
211     DLINK_FOREACH_SAFE(ptr, next_ptr, conf_modules.head)
212     {
213     pathst = ptr->data;
214    
215     dlinkDelete(&pathst->node, &conf_modules);
216     MyFree(pathst);
217     }
218     }
219    
220     /* findmodule_byname
221     *
222     * input - name of module
223     * output - NULL if not found or pointer to module
224     * side effects - NONE
225     */
226     dlink_node *
227     findmodule_byname(const char *name)
228     {
229     dlink_node *ptr;
230     struct module *modp;
231    
232     DLINK_FOREACH(ptr, mod_list.head)
233     {
234     modp = ptr->data;
235    
236 db 218 if (strcmp(modp->name, name) == 0)
237 adx 30 return ptr;
238     }
239    
240     return NULL;
241     }
242    
243     /* load_all_modules()
244     *
245     * input - int flag warn
246     * output - NONE
247     * side effects - load all modules found in autoload directory
248     */
249     void
250     load_all_modules(int warn)
251     {
252     DIR *system_module_dir = NULL;
253     struct dirent *ldirent = NULL;
254     char module_fq_name[PATH_MAX + 1];
255    
256     modules_init();
257    
258     if ((system_module_dir = opendir(AUTOMODPATH)) == NULL)
259     {
260     ilog(L_WARN, "Could not load modules from %s: %s",
261     AUTOMODPATH, strerror(errno));
262     return;
263     }
264    
265     while ((ldirent = readdir(system_module_dir)) != NULL)
266     {
267     const char *offset = strrchr(ldirent->d_name, '.');
268    
269     if (offset && !strcmp(offset, SHARED_SUFFIX))
270     {
271     snprintf(module_fq_name, sizeof(module_fq_name), "%s/%s",
272     AUTOMODPATH, ldirent->d_name);
273     load_a_module(module_fq_name, warn, 0);
274     }
275     }
276    
277     closedir(system_module_dir);
278     }
279    
280     /* load_conf_modules()
281     *
282     * input - NONE
283     * output - NONE
284     * side effects - load modules given in ircd.conf
285     */
286     void
287     load_conf_modules(void)
288     {
289     dlink_node *ptr = NULL;
290     struct module_path *mpath = NULL;
291    
292     DLINK_FOREACH(ptr, conf_modules.head)
293     {
294     mpath = ptr->data;
295    
296     if (findmodule_byname(mpath->path) == NULL)
297     load_one_module(mpath->path, 0);
298     }
299     }
300    
301     /* load_core_modules()
302     *
303     * input - int flag warn
304     * output - NONE
305     * side effects - core modules are loaded, if any fail, kill ircd
306     */
307     void
308     load_core_modules(int warn)
309     {
310     char module_name[PATH_MAX + 1];
311     int i = 0;
312    
313     for (; core_module_table[i]; ++i)
314     {
315     snprintf(module_name, sizeof(module_name), "%s%s%s", MODPATH,
316     core_module_table[i], SHARED_SUFFIX);
317    
318     if (load_a_module(module_name, warn, 1) == -1)
319     {
320     ilog(L_CRIT, "Error loading core module %s%s: terminating ircd",
321     core_module_table[i], SHARED_SUFFIX);
322     exit(EXIT_FAILURE);
323     }
324     }
325     }
326    
327     /* load_one_module()
328     *
329     * input - pointer to path
330     * - flagged as core module or not
331     * output - -1 if error
332     * side effects - module is loaded if found.
333     */
334     int
335     load_one_module(char *path, int coremodule)
336     {
337     dlink_node *ptr = NULL;
338     char modpath[PATH_MAX + 1];
339     struct stat statbuf;
340    
341     DLINK_FOREACH(ptr, mod_paths.head)
342     {
343     const struct module_path *mpath = ptr->data;
344    
345     snprintf(modpath, sizeof(modpath), "%s/%s", mpath->path, path);
346    
347     if (strstr(modpath, "../") == NULL &&
348     strstr(modpath, "/..") == NULL)
349     {
350     if (!stat(modpath, &statbuf))
351     {
352     if (S_ISREG(statbuf.st_mode))
353     {
354     /* Regular files only please */
355     return load_a_module(modpath, 1, coremodule);
356     }
357     }
358     }
359     }
360    
361     sendto_realops_flags(UMODE_ALL, L_ALL,
362     "Cannot locate module %s", path);
363     ilog(L_WARN, "Cannot locate module %s", path);
364     return -1;
365     }
366    
367     /* load a module .. */
368     static void
369     mo_modload(struct Client *client_p, struct Client *source_p,
370     int parc, char *parv[])
371     {
372     char *m_bn;
373    
374     if (!IsAdmin(source_p))
375     {
376     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
377     me.name, source_p->name);
378     return;
379     }
380    
381     m_bn = basename(parv[1]);
382    
383     if (findmodule_byname(m_bn) != NULL)
384     {
385     sendto_one(source_p, ":%s NOTICE %s :Module %s is already loaded",
386     me.name, source_p->name, m_bn);
387     return;
388     }
389    
390     load_one_module(parv[1], 0);
391     }
392    
393     /* unload a module .. */
394     static void
395     mo_modunload(struct Client *client_p, struct Client *source_p,
396     int parc, char *parv[])
397     {
398     char *m_bn;
399     dlink_node *ptr;
400     struct module *modp;
401    
402     if (!IsAdmin(source_p))
403     {
404     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
405     me.name, source_p->name);
406     return;
407     }
408    
409     m_bn = basename(parv[1]);
410    
411     if ((ptr = findmodule_byname(m_bn)) == NULL)
412     {
413     sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
414     me.name, source_p->name, m_bn);
415     return;
416     }
417    
418     modp = ptr->data;
419    
420     if (modp->core == 1)
421     {
422     sendto_one(source_p,
423     ":%s NOTICE %s :Module %s is a core module and may not be unloaded",
424     me.name, source_p->name, m_bn);
425     return;
426     }
427    
428     /* XXX might want to simply un dlink it here */
429    
430     if (unload_one_module(m_bn, 1) == -1)
431     {
432     sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
433     me.name, source_p->name, m_bn);
434     }
435     }
436    
437     /* unload and load in one! */
438     static void
439     mo_modreload(struct Client *client_p, struct Client *source_p,
440     int parc, char *parv[])
441     {
442     char *m_bn;
443     dlink_node *ptr;
444     struct module *modp;
445     int check_core;
446    
447     if (!IsAdmin(source_p))
448     {
449     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
450     me.name, source_p->name);
451     return;
452     }
453    
454     m_bn = basename(parv[1]);
455    
456     if ((ptr = findmodule_byname(m_bn)) == NULL)
457     {
458     sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
459     me.name, source_p->name, m_bn);
460     return;
461     }
462    
463     modp = ptr->data;
464     check_core = modp->core;
465    
466     if (unload_one_module(m_bn, 1) == -1)
467     {
468     sendto_one(source_p, ":%s NOTICE %s :Module %s is not loaded",
469     me.name, source_p->name, m_bn);
470     return;
471     }
472    
473     if ((load_one_module(parv[1], check_core) == -1) && check_core)
474     {
475     sendto_realops_flags(UMODE_ALL, L_ALL, "Error reloading core "
476     "module: %s: terminating ircd", parv[1]);
477     ilog(L_CRIT, "Error loading core module %s: terminating ircd", parv[1]);
478     exit(0);
479     }
480     }
481    
482     /* list modules .. */
483     static void
484     mo_modlist(struct Client *client_p, struct Client *source_p,
485     int parc, char *parv[])
486     {
487     dlink_node *ptr;
488     struct module *modp;
489    
490     if (!IsAdmin(source_p))
491     {
492     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
493     me.name, source_p->name);
494     return;
495     }
496    
497     DLINK_FOREACH(ptr, mod_list.head)
498     {
499     modp = ptr->data;
500    
501     if (parc > 1)
502     {
503     if (match(parv[1], modp->name))
504     {
505     sendto_one(source_p, form_str(RPL_MODLIST), me.name, parv[0],
506     modp->name, modp->address,
507     modp->version, modp->core?"(core)":"");
508     }
509     }
510     else
511     {
512     sendto_one(source_p, form_str(RPL_MODLIST), me.name, parv[0],
513     modp->name, modp->address,
514     modp->version, modp->core?"(core)":"");
515     }
516     }
517    
518     sendto_one(source_p, form_str(RPL_ENDOFMODLIST),
519     me.name, source_p->name);
520     }
521    
522     /* unload and reload all modules */
523     static void
524     mo_modrestart(struct Client *client_p, struct Client *source_p,
525     int parc, char *parv[])
526     {
527     unsigned int modnum = 0;
528     dlink_node *ptr;
529     dlink_node *tptr;
530     struct module *modp;
531    
532     if (!IsAdmin(source_p))
533     {
534     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
535     me.name, source_p->name);
536     return;
537     }
538    
539     sendto_one(source_p, ":%s NOTICE %s :Reloading all modules",
540     me.name, source_p->name);
541    
542     modnum = dlink_list_length(&mod_list);
543    
544     DLINK_FOREACH_SAFE(ptr, tptr, mod_list.head)
545     {
546     modp = ptr->data;
547     unload_one_module(modp->name, 0);
548     }
549    
550     load_all_modules(0);
551     load_conf_modules();
552     load_core_modules(0);
553    
554     sendto_realops_flags(UMODE_ALL, L_ALL,
555     "Module Restart: %u modules unloaded, %lu modules loaded",
556     modnum, dlink_list_length(&mod_list));
557     ilog(L_WARN, "Module Restart: %u modules unloaded, %lu modules loaded",
558     modnum, dlink_list_length(&mod_list));
559     }
560    
561     #else /* STATIC_MODULES */
562     #include "s_serv.h"
563    
564     /* load_all_modules()
565     *
566     * input - warn flag
567     * output - NONE
568     * side effects - all the msgtabs are added for static modules
569     */
570     void
571     load_all_modules(int warn)
572     {
573     mod_add_cmd(&error_msgtab);
574     mod_add_cmd(&accept_msgtab);
575     mod_add_cmd(&admin_msgtab);
576     mod_add_cmd(&away_msgtab);
577 michael 425 mod_add_cmd(&bmask_msgtab);
578 michael 512 mod_add_cmd(&cap_msgtab);
579 adx 30 mod_add_cmd(&capab_msgtab);
580     mod_add_cmd(&cburst_msgtab);
581     mod_add_cmd(&close_msgtab);
582     mod_add_cmd(&connect_msgtab);
583     #ifdef HAVE_LIBCRYPTO
584     mod_add_cmd(&challenge_msgtab);
585     mod_add_cmd(&cryptlink_msgtab);
586     #endif
587     mod_add_cmd(&die_msgtab);
588     mod_add_cmd(&drop_msgtab);
589     mod_add_cmd(&eob_msgtab);
590     mod_add_cmd(&etrace_msgtab);
591     mod_add_cmd(&gline_msgtab);
592     add_capability("GLN", CAP_GLN, 1);
593     mod_add_cmd(&hash_msgtab);
594     mod_add_cmd(&ungline_msgtab);
595     mod_add_cmd(&info_msgtab);
596     mod_add_cmd(&invite_msgtab);
597     mod_add_cmd(&ison_msgtab);
598     mod_add_cmd(&join_msgtab);
599     mod_add_cmd(&kick_msgtab);
600     mod_add_cmd(&kill_msgtab);
601     mod_add_cmd(&kline_msgtab);
602     add_capability("KLN", CAP_KLN, 1);
603     mod_add_cmd(&dline_msgtab);
604     mod_add_cmd(&unkline_msgtab);
605     mod_add_cmd(&undline_msgtab);
606     mod_add_cmd(&knock_msgtab);
607     add_capability("KNOCK", CAP_KNOCK, 1);
608     mod_add_cmd(&knockll_msgtab);
609     mod_add_cmd(&links_msgtab);
610     mod_add_cmd(&list_msgtab);
611     mod_add_cmd(&lljoin_msgtab);
612     mod_add_cmd(&llnick_msgtab);
613     mod_add_cmd(&locops_msgtab);
614     mod_add_cmd(&lusers_msgtab);
615     mod_add_cmd(&privmsg_msgtab);
616     mod_add_cmd(&notice_msgtab);
617     mod_add_cmd(&map_msgtab);
618     mod_add_cmd(&mode_msgtab);
619     mod_add_cmd(&motd_msgtab);
620     mod_add_cmd(&names_msgtab);
621     mod_add_cmd(&nburst_msgtab);
622     mod_add_cmd(&nick_msgtab);
623     mod_add_cmd(&omotd_msgtab);
624     mod_add_cmd(&oper_msgtab);
625     mod_add_cmd(&operwall_msgtab);
626     mod_add_cmd(&part_msgtab);
627     mod_add_cmd(&pass_msgtab);
628     mod_add_cmd(&ping_msgtab);
629     mod_add_cmd(&pong_msgtab);
630     mod_add_cmd(&post_msgtab);
631     mod_add_cmd(&get_msgtab);
632     mod_add_cmd(&put_msgtab);
633     mod_add_cmd(&quit_msgtab);
634     mod_add_cmd(&rehash_msgtab);
635     mod_add_cmd(&restart_msgtab);
636     mod_add_cmd(&resv_msgtab);
637     mod_add_cmd(&rkline_msgtab);
638     mod_add_cmd(&rxline_msgtab);
639     mod_add_cmd(&server_msgtab);
640     mod_add_cmd(&set_msgtab);
641     mod_add_cmd(&sid_msgtab);
642     mod_add_cmd(&sjoin_msgtab);
643     mod_add_cmd(&squit_msgtab);
644     mod_add_cmd(&stats_msgtab);
645     mod_add_cmd(&svinfo_msgtab);
646     mod_add_cmd(&tb_msgtab);
647     add_capability("TB", CAP_TB, 1);
648 michael 329 mod_add_cmd(&tburst_msgtab);
649     add_capability("TBURST", CAP_TBURST, 1);
650 adx 30 mod_add_cmd(&testline_msgtab);
651     mod_add_cmd(&testgecos_msgtab);
652     mod_add_cmd(&testmask_msgtab);
653     mod_add_cmd(&time_msgtab);
654 michael 425 mod_add_cmd(&tmode_msgtab);
655 adx 30 mod_add_cmd(&topic_msgtab);
656     mod_add_cmd(&trace_msgtab);
657     add_capability("UNKLN", CAP_UNKLN, 1);
658     mod_add_cmd(&uid_msgtab);
659     mod_add_cmd(&unresv_msgtab);
660     mod_add_cmd(&unxline_msgtab);
661     mod_add_cmd(&user_msgtab);
662     mod_add_cmd(&userhost_msgtab);
663     mod_add_cmd(&users_msgtab);
664     mod_add_cmd(&version_msgtab);
665     mod_add_cmd(&wallops_msgtab);
666 michael 876 mod_add_cmd(&watch_msgtab);
667 adx 30 mod_add_cmd(&who_msgtab);
668     mod_add_cmd(&whois_msgtab);
669     mod_add_cmd(&whowas_msgtab);
670     mod_add_cmd(&xline_msgtab);
671     mod_add_cmd(&help_msgtab);
672     mod_add_cmd(&uhelp_msgtab);
673     #ifdef BUILD_CONTRIB
674 michael 512 mod_add_cmd(&bs_msgtab);
675 adx 30 mod_add_cmd(&botserv_msgtab);
676     mod_add_cmd(&capture_msgtab);
677     mod_add_cmd(&chanserv_msgtab);
678     mod_add_cmd(&chghost_msgtab);
679     mod_add_cmd(&chgident_msgtab);
680     mod_add_cmd(&chgname_msgtab);
681     mod_add_cmd(&classlist_msgtab);
682     mod_add_cmd(&clearchan_msgtab);
683     mod_add_cmd(&cs_msgtab);
684     mod_add_cmd(&ctrace_msgtab);
685     mod_add_cmd(&delspoof_msgtab);
686     mod_add_cmd(&flags_msgtab);
687     mod_add_cmd(&forcejoin_msgtab);
688     mod_add_cmd(&forcepart_msgtab);
689     mod_add_cmd(&global_msgtab);
690     mod_add_cmd(&help_msgtab);
691     mod_add_cmd(&uhelp_msgtab);
692     mod_add_cmd(&helpserv_msgtab);
693     mod_add_cmd(&hostserv_msgtab);
694     mod_add_cmd(&identify_msgtab);
695     mod_add_cmd(&jupe_msgtab);
696     mod_add_cmd(&killhost_msgtab);
697     mod_add_cmd(&ltrace_msgtab);
698     mod_add_cmd(&memoserv_msgtab);
699     mod_add_cmd(&mkpasswd_msgtab);
700     mod_add_cmd(&ms_msgtab);
701     mod_add_cmd(&nickserv_msgtab);
702     mod_add_cmd(&ns_msgtab);
703     mod_add_cmd(&ojoin_msgtab);
704     mod_add_cmd(&operserv_msgtab);
705     mod_add_cmd(&operspy_msgtab);
706     mod_add_cmd(&opme_msgtab);
707     mod_add_cmd(&os_msgtab);
708     mod_add_cmd(&seenserv_msgtab);
709     mod_add_cmd(&spoof_msgtab);
710     mod_add_cmd(&statserv_msgtab);
711     mod_add_cmd(&svsnick_msgtab);
712     mod_add_cmd(&uncapture_msgtab);
713     /* FIXME: what about spy*? */
714     #endif
715     }
716     #endif /* STATIC_MODULES */

Properties

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