ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/protocol/dreamforge.C
Revision: 1.2
Committed: Sat Jul 21 01:29:09 2007 UTC (19 years, 2 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.1: +2 -2 lines
Log Message:
- moved to new documentation system
- fixed small build error

File Contents

# User Rev Content
1 pippijn 1.1 /*
2     * Copyright © 2003-2004 E. Will et al.
3     * Copyright © 2005-2006 Atheme Development Group
4 pippijn 1.2 * Rights to this code are documented in doc/pod/license.pod.
5 pippijn 1.1 *
6     * This file contains protocol support for bahamut-based ircd.
7     *
8 pippijn 1.2 * $Id: dreamforge.C,v 1.1 2007-07-19 08:24:55 pippijn Exp $
9 pippijn 1.1 */
10    
11     #include "atheme.h"
12     #include <account/mynick.h>
13     #include "uplink.h"
14     #include "pmodule.h"
15     #include "protocol/dreamforge.h"
16    
17     static char const rcsid[] = "$Id";
18    
19     struct dreamforge_listeners : callback::has_listeners
20     {
21     };
22    
23     dreamforge_listeners listeners;
24    
25     DECLARE_MODULE_V1 ("protocol/dreamforge", true, _modinit, NULL, rcsid, "The Ermyth Team <http://ermyth.schmorp.de>");
26    
27     /* *INDENT-OFF* */
28    
29     ircd_t DreamForge = {
30     "DreamForge 4.6.7 and later", /* IRCd name */
31     "$", /* TLD Prefix, used by Global. */
32     false, /* Whether or not we use IRCNet/TS6 UID */
33     false, /* Whether or not we use RCOMMAND */
34     false, /* Whether or not we support channel owners. */
35     false, /* Whether or not we support channel protection. */
36     false, /* Whether or not we support halfops. */
37     false, /* Whether or not we use P10 */
38     false, /* Whether or not we use vHosts. */
39     0, /* Oper-only cmodes */
40     0, /* Integer flag for owner channel flag. */
41     0, /* Integer flag for protect channel flag. */
42     0, /* Integer flag for halfops. */
43     "+", /* Mode we set for owner. */
44     "+", /* Mode we set for protect. */
45     "+", /* Mode we set for halfops. */
46     PROTOCOL_DREAMFORGE, /* Protocol type */
47     0, /* Permanent cmodes */
48     "b", /* Ban-like cmodes */
49     0, /* Except mchar */
50     0, /* Invex mchar */
51     0 /* Flags */
52     };
53    
54     cmode_t dreamforge_mode_list[] = {
55     { 'i', CMODE_INVITE },
56     { 'm', CMODE_MOD },
57     { 'n', CMODE_NOEXT },
58     { 'p', CMODE_PRIV },
59     { 's', CMODE_SEC },
60     { 't', CMODE_TOPIC },
61     { 'c', CMODE_NOCOLOR },
62     { 'R', CMODE_REGONLY },
63     { '\0', 0 }
64     };
65    
66     extmode dreamforge_ignore_mode_list[] = {
67     { '\0', 0 }
68     };
69    
70     cmode_t dreamforge_status_mode_list[] = {
71     { 'o', CMODE_OP },
72     { 'v', CMODE_VOICE },
73     { '\0', 0 }
74     };
75    
76     cmode_t dreamforge_prefix_mode_list[] = {
77     { '@', CMODE_OP },
78     { '+', CMODE_VOICE },
79     { '\0', 0 }
80     };
81    
82     /* *INDENT-ON* */
83    
84     /* login to our uplink */
85     static unsigned int
86     dreamforge_server_login (void)
87     {
88     int ret;
89    
90     ret = sts ("PASS %s", curr_uplink->pass);
91     if (ret == 1)
92     return 1;
93    
94     me.bursting = true;
95    
96     sts ("PROTOCTL NOQUIT WATCH=128 SAFELIST");
97     sts ("SERVER %s 1 :%s", me.name, me.desc);
98    
99     services_init ();
100    
101     return 0;
102     }
103    
104     /* introduce a client */
105     static void
106     dreamforge_introduce_nick (user_t *u)
107     {
108     sts ("NICK %s 1 %ld %s %s %s 0 :%s", u->nick, u->ts, u->user, u->host, me.name, u->gecos);
109     sts (":%s MODE %s +%s", u->nick, u->nick, "io");
110     }
111    
112     /* invite a user to a channel */
113     static void
114     dreamforge_invite_sts (user_t *sender, user_t *target, channel_t *channel)
115     {
116     sts (":%s INVITE %s %s", sender->nick, target->nick, channel->name);
117     }
118    
119     static void
120     dreamforge_quit_sts (user_t *u, const char *reason)
121     {
122     if (!me.connected)
123     return;
124    
125     sts (":%s QUIT :%s", u->nick, reason);
126     }
127    
128     /* WALLOPS wrapper */
129     static void
130     dreamforge_wallops_sts (const char *text)
131     {
132     sts (":%s GLOBOPS :%s", me.name, text);
133     }
134    
135     /* join a channel */
136     static void
137     dreamforge_join_sts (channel_t *c, user_t *u, bool isnew, char *modes)
138     {
139     if (isnew)
140     {
141     sts (":%s JOIN %s", u->nick, c->name);
142     if (modes[0] && modes[1])
143     sts (":%s MODE %s %s", u->nick, c->name, modes);
144     }
145     else
146     {
147     sts (":%s JOIN %s", u->nick, c->name);
148     }
149     sts (":%s MODE %s +o %s %ld", u->nick, c->name, u->nick, c->ts);
150     }
151    
152     /* kicks a user from a channel */
153     static void
154     dreamforge_kick (char *from, char *channel, char *to, char *reason)
155     {
156     channel_t *chan = channel_find (channel);
157     user_t *user = user_find (to);
158    
159     if (!chan || !user)
160     return;
161    
162     sts (":%s KICK %s %s :%s", from, channel, to, reason);
163    
164     chanuser_delete (chan, user);
165     }
166    
167     /* PRIVMSG wrapper */
168     static void
169     dreamforge_msg (const char *from, const char *target, const char *fmt, ...)
170     {
171     va_list ap;
172     char buf[BUFSIZE];
173    
174     va_start (ap, fmt);
175     vsnprintf (buf, BUFSIZE, fmt, ap);
176     va_end (ap);
177    
178     sts (":%s PRIVMSG %s :%s", from, target, buf);
179     }
180    
181     /* NOTICE wrapper */
182     static void
183     dreamforge_notice_user_sts (user_t *from, user_t *target, const char *text)
184     {
185     sts (":%s NOTICE %s :%s", from ? from->nick : me.name, target->nick, text);
186     }
187    
188     static void
189     dreamforge_notice_global_sts (user_t *from, const char *mask, const char *text)
190     {
191     node_t *n;
192     tld_t *tld;
193    
194     if (!strcmp (mask, "*"))
195     {
196     LIST_FOREACH (n, tldlist.head)
197     {
198     tld = static_cast<tld_t *> (n->data);
199     sts (":%s NOTICE %s*%s :%s", from ? from->nick : me.name, ircd->tldprefix, tld->name, text);
200     }
201     }
202     else
203     sts (":%s NOTICE %s%s :%s", from ? from->nick : me.name, ircd->tldprefix, mask, text);
204     }
205    
206     static void
207     dreamforge_notice_channel_sts (user_t *from, channel_t *target, const char *text)
208     {
209     sts (":%s NOTICE %s :%s", from ? from->nick : me.name, target->name, text);
210     }
211    
212     static void
213     dreamforge_numeric_sts (char *from, int numeric, char *target, char *fmt, ...)
214     {
215     va_list ap;
216     char buf[BUFSIZE];
217    
218     va_start (ap, fmt);
219     vsnprintf (buf, BUFSIZE, fmt, ap);
220     va_end (ap);
221    
222     sts (":%s %d %s %s", from, numeric, target, buf);
223     }
224    
225     /* KILL wrapper */
226     static void
227     dreamforge_skill (char *from, char *nick, char *fmt, ...)
228     {
229     va_list ap;
230     char buf[BUFSIZE];
231    
232     va_start (ap, fmt);
233     vsnprintf (buf, BUFSIZE, fmt, ap);
234     va_end (ap);
235    
236     sts (":%s KILL %s :%s!%s!%s (%s)", from, nick, from, from, from, buf);
237     }
238    
239     /* PART wrapper */
240     static void
241     dreamforge_part_sts (channel_t *c, user_t *u)
242     {
243     sts (":%s PART %s", u->nick, c->name);
244     }
245    
246     /* server-to-server KLINE wrapper */
247     static void
248     dreamforge_kline_sts (char *server, char *user, char *host, long duration, char *reason)
249     {
250     if (!me.connected)
251     return;
252    
253     sts (":%s AKILL %s %s %ld %s %ld :%s", me.name, host, user, duration, opersvs.nick, time (NULL), reason);
254     }
255    
256     /* server-to-server UNKLINE wrapper */
257     static void
258     dreamforge_unkline_sts (char *server, char *user, char *host)
259     {
260     if (!me.connected)
261     return;
262    
263     sts (":%s RAKILL %s %s", me.name, host, user);
264     }
265    
266     /* topic wrapper */
267     static void
268     dreamforge_topic_sts (channel_t *c, const char *setter, time_t ts, time_t prevts, const char *topic)
269     {
270     if (!me.connected)
271     return;
272    
273     if (ts < prevts || prevts == 0)
274     sts (":%s TOPIC %s %s %ld :%s", chansvs.nick, c->name, setter, ts, topic);
275     else if (prevts > 1)
276     {
277     ts = prevts - 1;
278     sts (":%s TOPIC %s %s %ld :%s", chansvs.nick, c->name, "topictime.wrong", ts, topic);
279     c->topicts = ts;
280     }
281     else
282     {
283     notice (chansvs.nick, c->name, "Unable to change topic to: %s", topic);
284     c->topicts = 1;
285     }
286     }
287    
288     /* mode wrapper */
289     static void
290     dreamforge_mode_sts (char *sender, channel_t *target, char *modes)
291     {
292     if (!me.connected)
293     return;
294    
295     sts (":%s MODE %s %s", sender, target->name, modes);
296     }
297    
298     /* ping wrapper */
299     static void
300     dreamforge_ping_sts (void)
301     {
302     if (!me.connected)
303     return;
304    
305     sts ("PING :%s", me.name);
306     }
307    
308     /* protocol-specific stuff to do on login */
309     static void
310     dreamforge_on_login (char *origin, char *user, char *wantedhost)
311     {
312     user_t *u = user_find (origin);
313    
314     if (!me.connected || u == NULL)
315     return;
316    
317     /* Can only do this for nickserv, and can only record identified
318     * state if logged in to correct nick, sorry -- jilles
319     */
320     if (should_reg_umode (u))
321     sts (":%s SVSMODE %s +rd %ld", nicksvs.nick, origin, time (NULL));
322     }
323    
324     /* protocol-specific stuff to do on login */
325     static bool
326     dreamforge_on_logout (char *origin, char *user, char *wantedhost)
327     {
328     if (!me.connected)
329     return false;
330    
331     if (!nicksvs.no_nick_ownership)
332     sts (":%s SVSMODE %s -r+d %ld", nicksvs.nick, origin, time (NULL));
333    
334     return false;
335     }
336    
337     static void
338     dreamforge_jupe (const char *server, const char *reason)
339     {
340     if (!me.connected)
341     return;
342    
343     server_delete (server);
344     sts (":%s SQUIT %s :%s", opersvs.nick, server, reason);
345     sts (":%s SERVER %s 2 :%s", me.name, server, reason);
346     }
347    
348     static void
349     m_topic (sourceinfo_t *si, int parc, char *parv[])
350     {
351     channel_t *c = channel_find (parv[0]);
352    
353     if (!c)
354     return;
355    
356     handle_topic_from (si, c, parv[1], atol (parv[2]), parv[3]);
357     }
358    
359     static void
360     m_ping (sourceinfo_t *si, int parc, char *parv[])
361     {
362     /* reply to PING's */
363     sts (":%s PONG %s %s", me.name, me.name, parv[0]);
364     }
365    
366     static void
367     m_pong (sourceinfo_t *si, int parc, char *parv[])
368     {
369     server_t *s;
370    
371     /* someone replied to our PING */
372     if (!parv[0])
373     return;
374     s = server_find (parv[0]);
375     if (s == NULL)
376     return;
377     handle_eob (s);
378    
379     if (irccasecmp (me.actual, parv[0]))
380     return;
381    
382     me.uplinkpong = NOW;
383    
384     /* -> :test.projectxero.net PONG test.projectxero.net :shrike.malkier.net */
385     if (me.bursting)
386     {
387     #ifdef HAVE_GETTIMEOFDAY
388     e_time (burstime, &burstime);
389    
390     slog (LG_INFO, "m_pong(): finished synching with uplink (%d %s)", (tv2ms (&burstime) > 1000) ? (tv2ms (&burstime) / 1000) : tv2ms (&burstime), (tv2ms (&burstime) > 1000) ? "s" : "ms");
391    
392     wallops ("Finished synching to network in %d %s.", (tv2ms (&burstime) > 1000) ? (tv2ms (&burstime) / 1000) : tv2ms (&burstime), (tv2ms (&burstime) > 1000) ? "s" : "ms");
393     #else
394     slog (LG_INFO, "m_pong(): finished synching with uplink");
395     wallops ("Finished synching to network.");
396     #endif
397    
398     me.bursting = false;
399     }
400     }
401    
402     static void
403     m_privmsg (sourceinfo_t *si, int parc, char *parv[])
404     {
405     if (parc != 2)
406     return;
407    
408     handle_message (si, parv[0], false, parv[1]);
409     }
410    
411     static void
412     m_notice (sourceinfo_t *si, int parc, char *parv[])
413     {
414     if (parc != 2)
415     return;
416    
417     handle_message (si, parv[0], true, parv[1]);
418     }
419    
420     static void
421     m_part (sourceinfo_t *si, int parc, char *parv[])
422     {
423     int chanc;
424     char *chanv[256];
425     int i;
426    
427     chanc = sjtoken (parv[0], ',', chanv);
428     for (i = 0; i < chanc; i++)
429     {
430     slog (LG_DEBUG, "m_part(): user left channel: %s -> %s", si->su->nick, chanv[i]);
431    
432     chanuser_delete (channel_find (chanv[i]), si->su);
433     }
434     }
435    
436     static void
437     m_nick (sourceinfo_t *si, int parc, char *parv[])
438     {
439     server_t *s;
440     bool realchange;
441    
442     if (parc == 8)
443     {
444     s = server_find (parv[5]);
445     if (!s)
446     {
447     slog (LG_DEBUG, "m_nick(): new user on nonexistant server: %s", parv[6]);
448     return;
449     }
450    
451     slog (LG_DEBUG, "m_nick(): new user on `%s': %s", s->name, parv[0]);
452    
453     user_add (parv[0], parv[3], parv[4], NULL, NULL, NULL, parv[7], s, atoi (parv[2]));
454    
455     /* Note: cannot rely on umode +r to see if they're identified
456     * -- jilles */
457    
458     handle_nickchange (user_find (parv[0]));
459     }
460    
461     /* if it's only 2 then it's a nickname change */
462     else if (parc == 2)
463     {
464     if (!si->su)
465     {
466     slog (LG_DEBUG, "m_nick(): server trying to change nick: %s", si->s != NULL ? si->s->name : "<none>");
467     return;
468     }
469    
470     slog (LG_DEBUG, "m_nick(): nickname change from `%s': %s", si->su->nick, parv[0]);
471    
472     realchange = irccasecmp (si->su->nick, parv[0]);
473    
474     user_changenick (si->su, parv[0], atoi (parv[1]));
475    
476     /* fix up +r if necessary -- jilles */
477     if (realchange && !nicksvs.no_nick_ownership)
478     {
479     if (should_reg_umode (si->su))
480     /* changed nick to registered one, reset +r */
481     sts (":%s SVSMODE %s +rd %ld", nicksvs.nick, parv[0], NOW);
482     else
483     /* changed from registered nick, remove +r */
484     sts (":%s SVSMODE %s -r+d %ld", nicksvs.nick, parv[0], NOW);
485     }
486    
487     handle_nickchange (si->su);
488     }
489     else
490     {
491     int i;
492     slog (LG_DEBUG, "m_nick(): got NICK with wrong number of params");
493    
494     for (i = 0; i < parc; i++)
495     slog (LG_DEBUG, "m_nick(): parv[%d] = %s", i, parv[i]);
496     }
497     }
498    
499     static void
500     m_quit (sourceinfo_t *si, int parc, char *parv[])
501     {
502     if (si->su->server == me.me)
503     {
504     slog (LG_DEBUG, "m_quit(): not destroying own user %s (fake direction)", si->su->nick);
505     return;
506     }
507     slog (LG_DEBUG, "m_quit(): user leaving: %s", si->su->nick);
508    
509     /* user_delete() takes care of removing channels and so forth */
510     user_delete (si->su);
511     }
512    
513     static void
514     m_mode (sourceinfo_t *si, int parc, char *parv[])
515     {
516     if (*parv[0] == '#')
517     channel_mode (NULL, channel_find (parv[0]), parc - 1, &parv[1]);
518     else
519     user_mode (user_find (parv[0]), parv[1]);
520     }
521    
522     static void
523     m_kick (sourceinfo_t *si, int parc, char *parv[])
524     {
525     user_t *u = user_find (parv[1]);
526     channel_t *c = channel_find (parv[0]);
527    
528     /* -> :rakaur KICK #shrike rintaun :test */
529     slog (LG_DEBUG, "m_kick(): user was kicked: %s -> %s", parv[1], parv[0]);
530    
531     if (!u)
532     {
533     slog (LG_DEBUG, "m_kick(): got kick for nonexistant user %s", parv[1]);
534     return;
535     }
536    
537     if (!c)
538     {
539     slog (LG_DEBUG, "m_kick(): got kick in nonexistant channel: %s", parv[0]);
540     return;
541     }
542    
543     if (!chanuser_find (c, u))
544     {
545     slog (LG_DEBUG, "m_kick(): got kick for %s not in %s", u->nick, c->name);
546     return;
547     }
548    
549     chanuser_delete (c, u);
550    
551     /* if they kicked us, let's rejoin */
552     if (is_internal_client (u))
553     {
554     slog (LG_DEBUG, "m_kick(): %s got kicked from %s; rejoining", u->nick, parv[0]);
555     join (parv[0], u->nick);
556     }
557     }
558    
559     static void
560     m_kill (sourceinfo_t *si, int parc, char *parv[])
561     {
562     handle_kill (si, parv[0], parc > 1 ? parv[1] : "<No reason given>");
563     }
564    
565     static void
566     m_squit (sourceinfo_t *si, int parc, char *parv[])
567     {
568     slog (LG_DEBUG, "m_squit(): server leaving: %s from %s", parv[0], parv[1]);
569     server_delete (parv[0]);
570     }
571    
572     static void
573     m_server (sourceinfo_t *si, int parc, char *parv[])
574     {
575     server_t *s;
576    
577     slog (LG_DEBUG, "m_server(): new server: %s", parv[0]);
578     s = handle_server (si, parv[0], NULL, atoi (parv[1]), parv[2]);
579    
580     if (s != NULL && s->uplink != me.me)
581     {
582     /* elicit PONG for EOB detection; pinging uplink is
583     * already done elsewhere -- jilles
584     */
585     sts (":%s PING %s %s", me.name, me.name, s->name);
586     }
587     }
588    
589     static void
590     m_stats (sourceinfo_t *si, int parc, char *parv[])
591     {
592     handle_stats (si->su, parv[0][0]);
593     }
594    
595     static void
596     m_admin (sourceinfo_t *si, int parc, char *parv[])
597     {
598     handle_admin (si->su);
599     }
600    
601     static void
602     m_version (sourceinfo_t *si, int parc, char *parv[])
603     {
604     handle_version (si->su);
605     }
606    
607     static void
608     m_info (sourceinfo_t *si, int parc, char *parv[])
609     {
610     handle_info (si->su);
611     }
612    
613     static void
614     m_whois (sourceinfo_t *si, int parc, char *parv[])
615     {
616     handle_whois (si->su, parv[1]);
617     }
618    
619     static void
620     m_trace (sourceinfo_t *si, int parc, char *parv[])
621     {
622     handle_trace (si->su, parv[0], parc >= 2 ? parv[1] : NULL);
623     }
624    
625     static void
626     m_away (sourceinfo_t *si, int parc, char *parv[])
627     {
628     handle_away (si->su, parc >= 1 ? parv[0] : NULL);
629     }
630    
631     static void
632     m_join (sourceinfo_t *si, int parc, char *parv[])
633     {
634     chanuser_t *cu;
635     node_t *n, *tn;
636     int chanc;
637     char *chanv[256];
638     int i;
639    
640     /* JOIN 0 is really a part from all channels */
641     if (parv[0][0] == '0')
642     {
643     LIST_FOREACH_SAFE (n, tn, si->su->channels.head)
644     {
645     cu = (chanuser_t *) n->data;
646     chanuser_delete (cu->chan, si->su);
647     }
648     }
649     else
650     {
651     chanc = sjtoken (parv[0], ',', chanv);
652     for (i = 0; i < chanc; i++)
653     {
654     channel_t *c = channel_find (chanv[i]);
655    
656     if (!c)
657     {
658     slog (LG_DEBUG, "m_join(): new channel: %s", parv[0]);
659     c = channel_add (chanv[i], NOW, si->su->server);
660     /* Tell the core to check mode locks now,
661     * otherwise it may only happen after the next
662     * mode change.
663     * DreamForge does not allow any redundant modes
664     * so this will not look ugly. -- jilles */
665     /* If this is in a burst, a MODE with the
666     * simple modes will follow so we can skip
667     * this. -- jilles */
668     if (!me.bursting)
669     channel_mode_va (NULL, c, 1, "+");
670     }
671     chanuser_add (c, si->su->nick);
672     }
673     }
674     }
675    
676     static void
677     m_pass (sourceinfo_t *si, int parc, char *parv[])
678     {
679     if (strcmp (curr_uplink->pass, parv[0]))
680     {
681     slog (LG_INFO, "m_pass(): password mismatch from uplink; aborting");
682     runflags |= RF_SHUTDOWN;
683     }
684     }
685    
686     static void
687     m_error (sourceinfo_t *si, int parc, char *parv[])
688     {
689     slog (LG_INFO, "m_error(): error from server: %s", parv[0]);
690     }
691    
692     static void
693     m_motd (sourceinfo_t *si, int parc, char *parv[])
694     {
695     handle_motd (si->su);
696     }
697    
698     static void
699     nick_group (hook_user_req_t * hdata)
700     {
701     user_t *u;
702    
703     u = hdata->si->su != NULL && !irccasecmp (hdata->si->su->nick, hdata->mn->nick) ? hdata->si->su : user_find_named (hdata->mn->nick);
704     if (u != NULL && should_reg_umode (u))
705     sts (":%s SVSMODE %s +rd %ld", nicksvs.nick, u->nick, time (NULL));
706     }
707    
708     static void
709     nick_ungroup (hook_user_req_t * hdata)
710     {
711     user_t *u;
712    
713     u = hdata->si->su != NULL && !irccasecmp (hdata->si->su->nick, hdata->mn->nick) ? hdata->si->su : user_find_named (hdata->mn->nick);
714     if (u != NULL && !nicksvs.no_nick_ownership)
715     sts (":%s SVSMODE %s -r+d %ld", nicksvs.nick, u->nick, time (NULL));
716     }
717    
718     void
719     _modinit (module_t *m)
720     {
721     /* Symbol relocation voodoo. */
722     server_login = &dreamforge_server_login;
723     introduce_nick = &dreamforge_introduce_nick;
724     quit_sts = &dreamforge_quit_sts;
725     wallops_sts = &dreamforge_wallops_sts;
726     join_sts = &dreamforge_join_sts;
727     kick = &dreamforge_kick;
728     msg = &dreamforge_msg;
729     notice_user_sts = &dreamforge_notice_user_sts;
730     notice_global_sts = &dreamforge_notice_global_sts;
731     notice_channel_sts = &dreamforge_notice_channel_sts;
732     numeric_sts = &dreamforge_numeric_sts;
733     skill = &dreamforge_skill;
734     part_sts = &dreamforge_part_sts;
735     kline_sts = &dreamforge_kline_sts;
736     unkline_sts = &dreamforge_unkline_sts;
737     topic_sts = &dreamforge_topic_sts;
738     mode_sts = &dreamforge_mode_sts;
739     ping_sts = &dreamforge_ping_sts;
740     ircd_on_login = &dreamforge_on_login;
741     ircd_on_logout = &dreamforge_on_logout;
742     jupe = &dreamforge_jupe;
743     invite_sts = &dreamforge_invite_sts;
744    
745     mode_list = dreamforge_mode_list;
746     ignore_mode_list = dreamforge_ignore_mode_list;
747     status_mode_list = dreamforge_status_mode_list;
748     prefix_mode_list = dreamforge_prefix_mode_list;
749    
750     ircd = &DreamForge;
751    
752     pcommand_add ("PING", m_ping, 1, MSRC_USER | MSRC_SERVER);
753     pcommand_add ("PONG", m_pong, 1, MSRC_SERVER);
754     pcommand_add ("PRIVMSG", m_privmsg, 2, MSRC_USER);
755     pcommand_add ("NOTICE", m_notice, 2, MSRC_UNREG | MSRC_USER | MSRC_SERVER);
756     pcommand_add ("PART", m_part, 1, MSRC_USER);
757     pcommand_add ("NICK", m_nick, 2, MSRC_USER | MSRC_SERVER);
758     pcommand_add ("QUIT", m_quit, 1, MSRC_USER);
759     pcommand_add ("MODE", m_mode, 2, MSRC_USER | MSRC_SERVER);
760     pcommand_add ("KICK", m_kick, 2, MSRC_USER | MSRC_SERVER);
761     pcommand_add ("KILL", m_kill, 1, MSRC_USER | MSRC_SERVER);
762     pcommand_add ("SQUIT", m_squit, 1, MSRC_USER | MSRC_SERVER);
763     pcommand_add ("SERVER", m_server, 3, MSRC_UNREG | MSRC_SERVER);
764     pcommand_add ("STATS", m_stats, 2, MSRC_USER);
765     pcommand_add ("ADMIN", m_admin, 1, MSRC_USER);
766     pcommand_add ("VERSION", m_version, 1, MSRC_USER);
767     pcommand_add ("INFO", m_info, 1, MSRC_USER);
768     pcommand_add ("WHOIS", m_whois, 2, MSRC_USER);
769     pcommand_add ("TRACE", m_trace, 1, MSRC_USER);
770     pcommand_add ("AWAY", m_away, 0, MSRC_USER);
771     pcommand_add ("JOIN", m_join, 1, MSRC_USER);
772     pcommand_add ("PASS", m_pass, 1, MSRC_UNREG);
773     pcommand_add ("ERROR", m_error, 1, MSRC_UNREG | MSRC_SERVER);
774     pcommand_add ("TOPIC", m_topic, 4, MSRC_USER | MSRC_SERVER);
775     pcommand_add ("MOTD", m_motd, 1, MSRC_USER);
776    
777     hook_add_event ("nick_group");
778     hook_add_hook ("nick_group", (void (*)(void *)) nick_group);
779     hook_add_event ("nick_ungroup");
780     hook_add_hook ("nick_ungroup", (void (*)(void *)) nick_ungroup);
781    
782     m->mflags = MODTYPE_CORE;
783    
784     pmodule_loaded = true;
785     }
786    
787     /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
788     * vim:ts=8
789     * vim:sw=8
790     * vim:noexpandtab
791     */