]> jfr.im git - irc/evilnet/x3.git/commitdiff
Removed bahamut support plus fixed a warning.
authorsirvulcan <redacted>
Tue, 1 Aug 2006 05:30:41 +0000 (05:30 +0000)
committersirvulcan <redacted>
Tue, 1 Aug 2006 05:30:41 +0000 (05:30 +0000)
17 files changed:
ChangeLog
INSTALL
configure
configure.in
patches/helpserv-pgsql.diff
patches/log-pgsql.diff
src/Makefile.am
src/Makefile.in
src/config.h.in
src/gline.c
src/global.c
src/hash.h
src/nickserv.c
src/nickserv.h
src/proto-bahamut.c [deleted file]
src/shun.c
x3.conf.example

index be1c15536be08ecb8d8d1478cb6c232fc71611a4..caaa9b0424be0e1cd6da05900a1eaed71471a03e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,46 @@
 /***********************************************************************
  X3 ChangeLog
 
+2006-08-01  Neil Spierling  <sirvulcan@gmail.com>
+
+       * This message is apart of the below one, its just seperate so
+       it doesnt get lost amongst the below messages.
+
+       * src/global.c: Fixed a warning.
+
+2006-08-01  Neil Spierling  <sirvulcan@gmail.com>
+
+       * configure: Removed bahamut support, didnt even work.
+
+       * configure.in: Removed bahamut support, didnt even work.
+
+       * INSTALL: Removed bahamut support, didnt even work.
+
+       * x3.conf.example: Removed bahamut support, didnt even work.
+
+       * patches/log-pgsql.diff: Removed bahamut support, didnt even work.
+
+       * patches/helpserv-pgsql.diff: Removed bahamut support, didnt even
+       work.
+
+       * src/config.h.in: Removed bahamut support, didnt even work.
+
+       * src/gline.c: Removed bahamut support, didnt even work.
+
+       * src/hash.h: Removed bahamut support, didnt even work.
+
+       * src/nickserv.c: Removed bahamut support, didnt even work.
+
+       * src/nickserv.h: Removed bahamut support, didnt even work.
+
+       * src/Makefile.am: Removed bahamut support, didnt even work.
+
+       * src/Makefile.in: Removed bahamut support, didnt even work.
+
+       * src/proto-bahamut.c: Removed bahamut support, didnt even work.
+
+       * src/shun.c: Removed bahamut support, didnt even work.
+
 2006-08-01  Neil Spierling  <sirvulcan@gmail.com>
 
        * src/global.c: Added language strings for mod-helpserv.c, opserv.c,
diff --git a/INSTALL b/INSTALL
index b55ff5425a7617cf51d18ee7a06845b1c9cb5371..b77d637e5be304278642e4ac2d835fea28d895d1 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -14,12 +14,12 @@ files.
 
 Requirements:
 ----------
-This release of X3 (1.4) only supports the Undernet P10 and Bahamut
-protocols and is known to link with ircu/Universal (u2.10.09),
-ircu/Undernet (u2.10.10, u2.10.11), ircu-lain, and Bahamut 1.4.32. It
-does not support hybrid, Unreal, or any other ircd not listed. Should
+This release of X3 (1.4) only supports the Undernet P10
+protocol and is known to link to ircu/Undernet (u2.10.11, u2.10.12),
+Nefarious IRCu 0.4.0 and Nefarious IRCu 1.0. It does not support 
+bahamut, hybrid, Unreal, or any other ircd not listed. Should
 you find other compatible ircds, please let us know.  Most of the
-testing has been done on Nefarious IRCu 0.4.0 (Based on ircu2.10.11.x).
+testing has been done on Nefarious IRCu 0.4.0/1.0 (Based on ircu2.10.11.x).
 
 X3 is known to compile on the following systems as long as you
 are using GNU make (make on Linux, gmake on many other systems):
@@ -54,9 +54,7 @@ Quick Install:
 $ ./configure
     NOTE: The protocol the resulting X3 binary will support is
     determined by the configure script. The P10 protocol is the
-    default; if you would like to link to Bahamut, you must pass
-    the --with-protocol=bahamut flag to the configure script:
-    $ ./configure --with-protocol=bahamut
+    default.
 $ make
 $ ${EDITOR} x3.conf
     NOTE: You may want to copy x3.conf.example to x3.conf and
@@ -73,8 +71,7 @@ Compiling:
      system will have the resources needed for X3 to compile.  If you
      would like to change the path where X3 will be installed to,
      execute configure with the --prefix=/path option.  The default path
-     is ~/X3-X.X.X/, with the X's representing the version.  See the
-     note in "Quick Install" if you are linking to Bahamut.
+     is ~/x3/, with the X's representing the version. 
 
   3) On some systems you may need to edit the Makefile in order for
      it to compile correctly.  Includes, and other such things may
index 74351ae676f40da742b7f9f6dc15ae01f9940858..ca46e5f2c4bdc920762f4bdeb258e81fbed80cc9 100755 (executable)
--- a/configure
+++ b/configure
@@ -870,7 +870,7 @@ Optional Packages:
   --with-malloc=type      Enables use of a special malloc library; one of:
                           system (the default), boehm-gc, dmalloc, mpatrol, x3, slab
   --with-protocol=name    Choose IRC dialect to support; one of:
-                          p10 (the default), bahamut
+                          p10 (the default)
   --without-getopt        Disables building of the GNU getopt library
   --with-tre=PATH    Base path to where libtre is installed, such that PATH/lib/libtre.so and PATH/include/tre/regex.h exist.
 
@@ -8201,16 +8201,6 @@ _ACEOF
   MODULE_OBJS="$MODULE_OBJS proto-p10.\$(OBJEXT)"
   PROTO_FILES=proto-p10.c
   x3_ircd="P10"
-elif test "x$withval" = "xbahamut" ; then
-  echo "$as_me:$LINENO: result: Bahamut" >&5
-echo "${ECHO_T}Bahamut" >&6
-
-cat >>confdefs.h <<\_ACEOF
-#define WITH_PROTOCOL_BAHAMUT 1
-_ACEOF
-
-  MODULE_OBJS="$MODULE_OBJS proto-bahamut.\$(OBJEXT)"
-  x3_ircd="Bahamut"
 else
   { { echo "$as_me:$LINENO: error: Unknown IRC dialect $withval" >&5
 echo "$as_me: error: Unknown IRC dialect $withval" >&2;}
index cfe32be262c9af96f5e8edd5d2473fd2e64d6430..4af8bfa3a29e6811cff1936f71eb13306f96eeae 100644 (file)
@@ -232,7 +232,7 @@ fi
 AC_MSG_CHECKING(which protocol to use)
 AC_ARG_WITH(protocol,
 [  --with-protocol=name    Choose IRC dialect to support; one of:
-                          p10 (the default), bahamut],
+                          p10 (the default)],
 [],
 [withval="p10"])
 if test "x$withval" = "xp10" ; then
@@ -241,11 +241,6 @@ if test "x$withval" = "xp10" ; then
   MODULE_OBJS="$MODULE_OBJS proto-p10.\$(OBJEXT)"
   PROTO_FILES=proto-p10.c
   x3_ircd="P10"
-elif test "x$withval" = "xbahamut" ; then
-  AC_MSG_RESULT(Bahamut)
-  AC_DEFINE(WITH_PROTOCOL_BAHAMUT, 1, [Define if using the Bahamut dialect of IRC])
-  MODULE_OBJS="$MODULE_OBJS proto-bahamut.\$(OBJEXT)"
-  x3_ircd="Bahamut"
 else
   AC_MSG_ERROR([Unknown IRC dialect $withval])
 fi
index b2602b061155befe6eab526eeadbe849f0c242ed..df2c1530d8ffe6844aa0fe6630cb328999e08018 100644 (file)
@@ -8,7 +8,7 @@ diff -u -r1.59 Makefile.am
 @@ -9,7 +9,7 @@
        ./expnhelp < $(srcdir)/nickserv.help.m4 > $@
  
- EXTRA_srvx_SOURCES = proto-bahamut.c proto-common.c proto-p10.c mod-snoop.c mod-memoserv.c
+ EXTRA_srvx_SOURCES = proto-common.c proto-p10.c mod-snoop.c mod-memoserv.c
 -srvx_LDADD = @MODULE_OBJS@
 +srvx_LDADD = @MODULE_OBJS@ -lpq
  srvx_DEPENDENCIES = @MODULE_OBJS@
index f0818b5dfc3dd8d22044b0eaf2d6c7f2fb30d8a2..91cb258167c84f9a3fa864604e660bdc4f61a796 100644 (file)
@@ -8,7 +8,7 @@ diff -u -r1.59 Makefile.am
 @@ -9,7 +9,7 @@
        ./expnhelp < $(srcdir)/nickserv.help.m4 > $@
  
- EXTRA_srvx_SOURCES = proto-bahamut.c proto-common.c proto-p10.c mod-snoop.c mod-memoserv.c
+ EXTRA_srvx_SOURCES = proto-common.c proto-p10.c mod-snoop.c mod-memoserv.c
 -srvx_LDADD = @MODULE_OBJS@
 +srvx_LDADD = @MODULE_OBJS@ -lpq
  srvx_DEPENDENCIES = @MODULE_OBJS@
index cc8772c1930c5e867466aef7a1474b3d7fc5a991..a4830ecbf9a28fad01fe1bee4bfc48de4fe7da90 100644 (file)
@@ -7,7 +7,7 @@ EXTRA_PROGRAMS = checkdb globtest
 noinst_DATA = chanserv.help global.help modcmd.help nickserv.help opserv.help saxdb.help sendmail.help spamserv.help mod-sockcheck.help mod-helpserv.help mod-memoserv.help
 EXTRA_DIST = $(noinst_DATA)
 
-EXTRA_x3_SOURCES = alloc-slab.c alloc-x3.c proto-bahamut.c proto-common.c proto-p10.c mod-snoop.c mod-track.c mod-memoserv.c mod-helpserv.c mod-sockcheck.c
+EXTRA_x3_SOURCES = alloc-slab.c alloc-x3.c proto-common.c proto-p10.c mod-snoop.c mod-track.c mod-memoserv.c mod-helpserv.c mod-sockcheck.c
 x3_LDADD = @MODULE_OBJS@
 x3_DEPENDENCIES = @MODULE_OBJS@
 x3_SOURCES = \
index 38075b1cf558d4c365a17ad31d851a010e2a3794..8e9377034a940472b0cc81f21225e3b11bea8ee7 100644 (file)
@@ -184,7 +184,7 @@ target_vendor = @target_vendor@
 AM_CPPFLAGS = @RX_INCLUDES@
 noinst_DATA = chanserv.help global.help modcmd.help nickserv.help opserv.help saxdb.help sendmail.help spamserv.help mod-sockcheck.help mod-helpserv.help mod-memoserv.help
 EXTRA_DIST = $(noinst_DATA)
-EXTRA_x3_SOURCES = alloc-slab.c alloc-x3.c proto-bahamut.c proto-common.c proto-p10.c mod-snoop.c mod-track.c mod-memoserv.c mod-helpserv.c mod-sockcheck.c
+EXTRA_x3_SOURCES = alloc-slab.c alloc-x3.c proto-common.c proto-p10.c mod-snoop.c mod-track.c mod-memoserv.c mod-helpserv.c mod-sockcheck.c
 x3_LDADD = @MODULE_OBJS@
 x3_DEPENDENCIES = @MODULE_OBJS@
 x3_SOURCES = \
@@ -322,7 +322,6 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/nickserv.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opserv.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/policer.Po@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto-bahamut.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto-common.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proto-p10.Po@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recdb.Po@am__quote@
index 9d3a98ec37a4e9009da7e98bfad9948918d68bdb..5eed96ec33a1baafa0b9bfefc699489d9c7ca18f 100644 (file)
 /* Define if using the X3 internal debug allocator */
 #undef WITH_MALLOC_X3
 
-/* Define if using the Bahamut dialect of IRC */
-#undef WITH_PROTOCOL_BAHAMUT
-
 /* Define if using the P10 dialect of IRC */
 #undef WITH_PROTOCOL_P10
 
index 39d40363a3510071fee731bcd75be7d514fdd47a..fbaba6cf02343dbe8f9850e0034722c0421d3ca6 100644 (file)
@@ -122,12 +122,6 @@ gline_remove(const char *target, int announce)
             timeq_add(new_first->expires, gline_expire, 0);
         }
     }
-#ifdef WITH_PROTOCOL_BAHAMUT
-    /* Bahamut is sort of lame: It permanently remembers any AKILLs
-     * with durations longer than a day, and will never auto-expire
-     * them.  So when the time comes, we'd better remind it.  */
-    announce = 1;
-#endif
     if (announce)
         irc_ungline(target);
     return res;
index 63702a658a55460788ea8e81f7d0657e9d251d73..0faf87b38466453c30a2ee07f393ec928231a485 100644 (file)
@@ -403,7 +403,7 @@ message_send(struct globalMessage *message)
 void
 global_message_args(long targets, const char *language_entry, ...)
 {
-    struct globalMessage *message;
+    struct globalMessage *message = NULL;
     va_list arg_list;
     dict_iterator_t it;
     char response[MAXLEN];
index 1cceb219d7af5d10d4b85500ff0a269ce594f603..642aa5f3beb742852731bd1350b143e59d4f2767 100644 (file)
@@ -37,7 +37,7 @@
 #define MODE_BAN               0x00000200 /* +b BAN */
 #define MODE_LIMIT             0x00000400 /* +l LIMIT */
 #define MODE_DELAYJOINS         0x00000800 /* +D */
-#define MODE_REGONLY            0x00001000 /* ircu +r, Bahamut +R */
+#define MODE_REGONLY            0x00001000 /* ircu +r */
 #define MODE_NOCOLORS           0x00002000 /* +c */
 #define MODE_NOCTCPS            0x00004000 /* +C */
 #define MODE_REGISTERED         0x00008000 /* Bahamut +r */
index ccd9748dae74c0c97c4cf197891fff939a3dc520..3cb699223c56e7bfa7f88db6e790a7d54cd92afa 100644 (file)
@@ -459,32 +459,6 @@ register_handle(const char *handle, const char *passwd, UNUSED_ARG(unsigned long
 {
     struct handle_info *hi;
 
-#ifdef WITH_PROTOCOL_BAHAMUT
-    char id_base64[IDLEN + 1];
-    do
-    {
-        /* Assign a unique account ID to the account; note that 0 is
-           an invalid account ID. 1 is therefore the first account ID. */
-        if (!id) {
-            id = 1 + highest_id++;
-        } else {
-            /* Note: highest_id is and must always be the highest ID. */
-            if(id > highest_id) {
-                highest_id = id;
-            }
-        }
-        inttobase64(id_base64, id, IDLEN);
-
-        /* Make sure an account with the same ID doesn't exist. If a
-           duplicate is found, log some details and assign a new one.
-           This should be impossible, but it never hurts to expect it. */
-        if ((hi = dict_find(nickserv_id_dict, id_base64, NULL))) {
-            log_module(NS_LOG, LOG_WARNING, "Duplicated account ID %lu (%s) found belonging to %s while inserting %s.", id, id_base64, hi->handle, handle);
-            id = 0;
-        }
-    } while(!id);
-#endif
-
     hi = calloc(1, sizeof(*hi));
     hi->userlist_style = HI_DEFAULT_STYLE;
     hi->announcements = '?';
@@ -493,11 +467,6 @@ register_handle(const char *handle, const char *passwd, UNUSED_ARG(unsigned long
     hi->infoline = NULL;
     dict_insert(nickserv_handle_dict, hi->handle, hi);
 
-#ifdef WITH_PROTOCOL_BAHAMUT
-    hi->id = id;
-    dict_insert(nickserv_id_dict, strdup(id_base64), hi);
-#endif
-
     return hi;
 }
 
@@ -570,13 +539,6 @@ free_handle_info(void *vhi)
 {
     struct handle_info *hi = vhi;
 
-#ifdef WITH_PROTOCOL_BAHAMUT
-    char id[IDLEN + 1];
-
-    inttobase64(id, hi->id, IDLEN);
-    dict_remove(nickserv_id_dict, id);
-#endif
-
     free_string_list(hi->masks);
     free_string_list(hi->ignores);
     assert(!hi->users);
@@ -1031,11 +993,7 @@ set_user_handle_info(struct userNode *user, struct handle_info *hi, int stamp)
             apply_fakehost(hi);
 
         if (stamp) {
-#ifdef WITH_PROTOCOL_BAHAMUT
-            /* Stamp users with their account ID. */
-            char id[IDLEN + 1];
-            inttobase64(id, hi->id, IDLEN);
-#elif WITH_PROTOCOL_P10
+#ifdef WITH_PROTOCOL_P10
             /* Stamp users with their account name. */
             char *id = hi->handle;
 #else
@@ -1585,9 +1543,6 @@ static NICKSERV_FUNC(cmd_handleinfo)
     nsmsg_none = handle_find_message(hi, "MSG_NONE");
     reply("NSMSG_HANDLEINFO_ON", hi->handle);
     reply("MSG_BAR");
-#ifdef WITH_PROTOCOL_BAHAMUT
-    reply("NSMSG_HANDLEINFO_ID", hi->id);
-#endif
     reply("NSMSG_HANDLEINFO_REGGED", ctime(&hi->registered));
 
     if (!hi->users) {
@@ -3319,9 +3274,6 @@ nickserv_saxdb_write(struct saxdb_context *ctx) {
 
     for (it = dict_first(nickserv_handle_dict); it; it = iter_next(it)) {
         hi = iter_data(it);
-#ifdef WITH_PROTOCOL_BAHAMUT
-        assert(hi->id);
-#endif
         saxdb_start_record(ctx, iter_key(it), 0);
         if (hi->announcements != '?') {
             flags[0] = hi->announcements;
@@ -3372,9 +3324,6 @@ nickserv_saxdb_write(struct saxdb_context *ctx) {
             flags[flen] = 0;
             saxdb_write_string(ctx, KEY_FLAGS, flags);
         }
-#ifdef WITH_PROTOCOL_BAHAMUT
-        saxdb_write_int(ctx, KEY_ID, hi->id);
-#endif
         if (hi->infoline)
             saxdb_write_string(ctx, KEY_INFO, hi->infoline);
         if (hi->last_quit_host[0])
index 78f7d856383f6870df116deab9d5c57f9ca1832e..73e2e929cf2aa6e4c2c8f8f6d17e078f6148e50b 100644 (file)
@@ -101,9 +101,6 @@ struct handle_info {
     char *infoline;
     char *handle;
     char *fakehost;
-#ifdef WITH_PROTOCOL_BAHAMUT
-    unsigned long id;
-#endif
     time_t registered;
     time_t lastseen;
     unsigned short flags;
diff --git a/src/proto-bahamut.c b/src/proto-bahamut.c
deleted file mode 100644 (file)
index 224bfed..0000000
+++ /dev/null
@@ -1,1517 +0,0 @@
-/* proto-bahamut.c - IRC protocol output
- * Copyright 2000-2004 srvx Development Team
- *
- * This file is part of srvx.
- *
- * x3 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with srvx; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
- */
-
-#include "proto-common.c"
-
-#define CAPAB_TS3       0x01
-#define CAPAB_NOQUIT    0x02
-#define CAPAB_SSJOIN    0x04
-#define CAPAB_BURST     0x08
-#define CAPAB_UNCONNECT 0x10
-#define CAPAB_NICKIP    0x20
-#define CAPAB_TSMODE    0x40
-#define CAPAB_ZIP       0x80
-
-struct service_message_info {
-    privmsg_func_t on_privmsg;
-    privmsg_func_t on_notice;
-};
-
-static dict_t service_msginfo_dict; /* holds service_message_info structs */
-static int uplink_capab;
-static void privmsg_user_helper(struct userNode *un, void *data);
-
-void irc_svsmode(struct userNode *target, char *modes, unsigned long stamp);
-
-struct server *
-AddServer(struct server *uplink, const char *name, int hops, time_t boot, time_t link, UNUSED_ARG(const char *numeric), const char *description) {
-    struct server* sNode;
-
-    sNode = calloc(1, sizeof(*sNode));
-    sNode->uplink = uplink;
-    safestrncpy(sNode->name, name, sizeof(sNode->name));
-    sNode->hops = hops;
-    sNode->boot = boot;
-    sNode->link = link;
-    sNode->users = dict_new();
-    safestrncpy(sNode->description, description, sizeof(sNode->description));
-    serverList_init(&sNode->children);
-    if (sNode->uplink) {
-        /* uplink may be NULL if we're just building ourself */
-        serverList_append(&sNode->uplink->children, sNode);
-    }
-    dict_insert(servers, sNode->name, sNode);
-
-    if (hops && !self->burst) {
-        unsigned int n;
-        for (n=0; n<slf_used; n++) {
-            slf_list[n](sNode);
-        }
-    }
-
-    return sNode;
-}
-
-void
-DelServer(struct server* serv, int announce, const char *message) {
-    unsigned int nn;
-    dict_iterator_t it, next;
-
-    if (!serv) return;
-    if (announce && (serv->uplink == self) && (serv != self->uplink)) {
-        irc_squit(serv, message, NULL);
-    }
-    for (nn=serv->children.used; nn>0;) {
-        if (serv->children.list[--nn] != self) {
-            DelServer(serv->children.list[nn], false, "uplink delinking");
-        }
-    }
-    for (it=dict_first(serv->users); it; it=next) {
-        next = iter_next(it);
-        DelUser(iter_data(it), NULL, false, "server delinking");
-    }
-    if (serv->uplink) serverList_remove(&serv->uplink->children, serv);
-    if (serv == self->uplink) self->uplink = NULL;
-    dict_remove(servers, serv->name);
-    serverList_clean(&serv->children);
-    dict_delete(serv->users);
-    free(serv);
-}
-
-int
-is_valid_nick(const char *nick) {
-    /* IRC has some of The Most Fucked-Up ideas about character sets
-     * in the world.. */
-    if ((*nick < 'A') || (*nick >= '~')) return 0;
-    for (++nick; *nick; ++nick) {
-        if (!((*nick >= 'A') && (*nick < '~'))
-            && !isdigit(*nick)
-            && (*nick != '-')) {
-            return 0;
-        }
-    }
-    if (strlen(nick) > nicklen) return 0;
-    return 1;
-}
-
-struct userNode *
-AddUser(struct server* uplink, const char *nick, const char *ident, const char *hostname, const char *modes, const char *userinfo, time_t timestamp, irc_in_addr_t realip, const char *stamp) {
-    struct userNode *uNode, *oldUser;
-    unsigned int nn;
-
-    if (!uplink) {
-        log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): server does not exist!", uplink, nick);
-        return NULL;
-    }
-
-    if (!is_valid_nick(nick)) {
-        log_module(MAIN_LOG, LOG_WARNING, "AddUser(%p, %s, ...): invalid nickname detected.", uplink, nick);
-        return NULL;
-    }
-
-    if ((oldUser = GetUserH(nick))) {
-        if (IsLocal(oldUser) && IsService(oldUser)) {
-            /* The service should collide the new user off. */
-            oldUser->timestamp = timestamp - 1;
-            irc_user(oldUser);
-        }
-        if (oldUser->timestamp > timestamp) {
-            /* "Old" user is really newer; remove them */
-            DelUser(oldUser, 0, 1, "Overruled by older nick");
-        } else {
-            /* User being added is too new */
-            return NULL;
-        }
-    }
-
-    uNode = calloc(1, sizeof(*uNode));
-    uNode->nick = strdup(nick);
-    safestrncpy(uNode->ident, ident, sizeof(uNode->ident));
-    safestrncpy(uNode->info, userinfo, sizeof(uNode->info));
-    safestrncpy(uNode->hostname, hostname, sizeof(uNode->hostname));
-    uNode->ip = realip;
-    uNode->timestamp = timestamp;
-    modeList_init(&uNode->channels);
-    uNode->uplink = uplink;
-    dict_insert(uplink->users, uNode->nick, uNode);
-    if (++uNode->uplink->clients > uNode->uplink->max_clients) {
-        uNode->uplink->max_clients = uNode->uplink->clients;
-    }
-
-    dict_insert(clients, uNode->nick, uNode);
-    if (dict_size(clients) > max_clients) {
-        max_clients = dict_size(clients);
-        max_clients_time = now;
-    }
-
-    mod_usermode(uNode, modes);
-    if (stamp) call_account_func(uNode, stamp);
-    if (IsLocal(uNode)) irc_user(uNode);
-    for (nn=0; nn<nuf_used; nn++) {
-        if (nuf_list[nn](uNode)) break;
-    }
-    return uNode;
-}
-
-struct userNode *
-AddService(const char *nick, const char *modes, const char *desc, const char *hostname) {
-    time_t timestamp = now;
-    struct userNode *old_user = GetUserH(nick);
-    static const irc_in_addr_t ipaddr;
-    if (old_user) {
-        if (IsLocal(old_user))
-            return old_user;
-        timestamp = old_user->timestamp - 1;
-    }
-    if (!hostname)
-        hostname = self->name;
-    return AddUser(self, nick, nick, hostname, modes ? modes : "+oikr", desc, timestamp, ipaddr, 0);
-}
-
-struct userNode *
-AddClone(const char *nick, const char *ident, const char *hostname, const char *desc) {
-    time_t timestamp = now;
-    struct userNode *old_user = GetUserH(nick);
-    static const irc_in_addr_t ipaddr;
-    if (old_user) {
-        if (IsLocal(old_user))
-            return old_user;
-        timestamp = old_user->timestamp - 1;
-    }
-    return AddUser(self, nick, ident, hostname, "+ir", desc, timestamp, ipaddr, 0);
-}
-
-void
-free_user(struct userNode *user)
-{
-    free(user->nick);
-    free(user);
-}
-
-void
-DelUser(struct userNode* user, struct userNode *killer, int announce, const char *why) {
-    unsigned int nn;
-
-    for (nn=user->channels.used; nn>0;) {
-        DelChannelUser(user, user->channels.list[--nn]->channel, false, 0);
-    }
-    for (nn=duf_used; nn>0; ) duf_list[--nn](user, killer, why);
-    user->uplink->clients--;
-    dict_remove(user->uplink->users, user->nick);
-    if (IsOper(user)) userList_remove(&curr_opers, user);
-    if (IsInvisible(user)) invis_clients--;
-    if (user == dict_find(clients, user->nick, NULL)) dict_remove(clients, user->nick);
-    if (announce) {
-        if (IsLocal(user)) {
-            irc_quit(user, why);
-        } else {
-            irc_kill(killer, user, why);
-        }
-    }
-    modeList_clean(&user->channels);
-    user->dead = 1;
-    if (dead_users.size) {
-        userList_append(&dead_users, user);
-    } else {
-        free_user(user);
-    }
-}
-
-void
-irc_server(struct server *srv) {
-    if (srv == self) {
-        putsock("SERVER %s %d :%s", srv->name, srv->hops, srv->description);
-    } else {
-        putsock(":%s SERVER %s %d :%s", self->name, srv->name, srv->hops, srv->description);
-    }
-}
-
-void
-irc_user(struct userNode *user) {
-    char modes[32];
-    int modelen = 0;
-    if (IsOper(user)) modes[modelen++] = 'o';
-    if (IsInvisible(user)) modes[modelen++] = 'i';
-    if (IsWallOp(user)) modes[modelen++] = 'w';
-    if (IsService(user)) modes[modelen++] = 'k';
-    if (IsServNotice(user)) modes[modelen++] = 's';
-    if (IsDeaf(user)) modes[modelen++] = 'd';
-    if (IsReggedNick(user)) modes[modelen++] = 'r';
-    if (IsGlobal(user)) modes[modelen++] = 'g';
-    modes[modelen] = 0;
-    putsock("NICK %s %d "FMT_TIME_T" +%s %s %s %s %d %u :%s",
-            user->nick, user->uplink->hops+2, user->timestamp, modes,
-            user->ident, user->hostname, user->uplink->name, 0, ntohl(user->ip.in6_32[3]), user->info);
-}
-
-void
-irc_account(struct userNode *user, const char *stamp)
-{
-    if (IsReggedNick(user)) {
-        irc_svsmode(user, "+rd", base64toint(stamp, IDLEN));
-    } else {
-        irc_svsmode(user, "+d", base64toint(stamp, IDLEN));
-    }
-}
-
-void
-irc_fakehost(UNUSED_ARG(struct userNode *user), UNUSED_ARG(const char *host))
-{
-    /* not supported in bahamut */
-}
-
-void
-irc_regnick(struct userNode *user)
-{
-    if (IsReggedNick(user)) {
-        irc_svsmode(user, "+r", 0);
-    } else {
-        irc_svsmode(user, "-r", 0);
-    }
-}
-
-void
-irc_nick(struct userNode *user, const char *old_nick) {
-    if (user->uplink == self) {
-        /* update entries in PRIVMSG/NOTICE handlers (if they exist) */
-        struct service_message_info *smi = dict_find(service_msginfo_dict, user->nick, NULL);
-        if (smi) {
-            dict_remove2(service_msginfo_dict, old_nick, 1);
-            dict_insert(service_msginfo_dict, user->nick, smi);
-        }
-    }
-    putsock(":%s NICK %s :"FMT_TIME_T, old_nick, user->nick, user->timestamp);
-}
-
-void
-irc_pass(const char *passwd) {
-    putsock("PASS %s :TS", passwd);
-}
-
-void
-irc_capab() {
-    putsock("CAPAB TS3 NOQUIT SSJOIN BURST UNCONNECT NICKIP TSMODE");
-}
-
-void
-irc_svinfo() {
-    putsock("SVINFO 3 3 0 :"FMT_TIME_T, now);
-}
-
-void
-irc_introduce(const char *passwd) {
-    extern time_t burst_begin;
-
-    irc_pass(passwd);
-    irc_capab();
-    irc_server(self);
-    irc_svinfo();
-    burst_length = 0;
-    burst_begin = now;
-    timeq_add(now + ping_freq, timed_send_ping, 0);
-}
-
-void
-irc_ping(const char *something) {
-    putsock("PING :%s", something);
-}
-
-void
-irc_pong(const char *who, const char *data) {
-    putsock(":%s PONG %s :%s", self->name, who, data);
-}
-
-void
-irc_quit(struct userNode *user, const char *message) {
-    putsock(":%s QUIT :%s", user->nick, message);
-}
-
-void
-irc_squit(struct server *srv, const char *message, const char *service_message) {
-    if (!service_message) service_message = message;
-    /* If we're leaving the network, QUIT all our clients. */
-    if ((srv == self) && (cManager.uplink->state == CONNECTED)) {
-        dict_iterator_t it;
-        for (it = dict_first(srv->users); it; it = iter_next(it)) {
-            irc_quit(iter_data(it), service_message);
-        }
-    }
-    putsock(":%s SQUIT %s 0 :%s", self->name, srv->name, message);
-    if (srv == self) {
-        /* Reconnect to the currently selected server. */
-        cManager.uplink->tries = 0;
-        log_module(MAIN_LOG, LOG_INFO, "Squitting from uplink: %s", message);
-        close_socket();
-    }
-}
-
-void
-irc_privmsg(struct userNode *from, const char *to, const char *message) {
-    putsock(":%s PRIVMSG %s :%s", from->nick, to, message);
-}
-
-void
-irc_notice(struct userNode *from, const char *to, const char *message) {
-    putsock(":%s NOTICE %s :%s", from->nick, to, message);
-}
-
-void
-irc_notice_user(struct userNode *from, struct userNode *to, const char *message) {
-    putsock(":%s NOTICE %s :%s", from->nick, to->nick, message);
-}
-
-void
-irc_wallchops(UNUSED_ARG(struct userNode *from), UNUSED_ARG(const char *to), UNUSED_ARG(const char *message)) {
-}
-
-void
-irc_join(struct userNode *who, struct chanNode *what) {
-    if (what->members.used == 1) {
-        putsock(":%s SJOIN "FMT_TIME_T" %s + :@%s", self->name, what->timestamp, what->name, who->nick);
-    } else {
-        putsock(":%s SJOIN "FMT_TIME_T" %s", who->nick, what->timestamp, what->name);
-    }
-}
-
-void
-irc_invite(struct userNode *from, struct userNode *who, struct chanNode *to) {
-    putsock(":%s INVITE %s %s", from->nick, who->nick, to->name);
-}
-
-void
-irc_mode(struct userNode *who, struct chanNode *target, const char *modes) {
-    putsock(":%s MODE %s "FMT_TIME_T" %s", who->nick, target->name, target->timestamp, modes);
-}
-
-void
-irc_svsmode(struct userNode *target, char *modes, unsigned long stamp) {
-    extern struct userNode *nickserv;
-    if (stamp) {
-       putsock(":%s SVSMODE %s "FMT_TIME_T" %s %lu", nickserv->nick, target->nick, target->timestamp, modes, stamp);
-    } else {
-       putsock(":%s SVSMODE %s "FMT_TIME_T" %s", nickserv->nick, target->nick, target->timestamp, modes);
-    }
-}
-
-void
-irc_kick(struct userNode *who, struct userNode *target, struct chanNode *from, const char *msg) {
-    putsock(":%s KICK %s %s :%s", who->nick, from->name, target->nick, msg);
-    ChannelUserKicked(who, target, from);
-}
-
-void
-irc_part(struct userNode *who, struct chanNode *what, const char *reason) {
-    if (reason) {
-        putsock(":%s PART %s :%s", who->nick, what->name, reason);
-    } else {
-        putsock(":%s PART %s", who->nick, what->name);
-    }
-}
-
-void
-irc_topic(struct userNode *who, struct chanNode *what, const char *topic) {
-    putsock(":%s TOPIC %s :%s", who->nick, what->name, topic);
-}
-
-void
-irc_fetchtopic(struct userNode *from, const char *to) {
-    if (!from || !to) return;
-    putsock(":%s TOPIC %s", from->nick, to);
-}
-
-void
-irc_gline(struct server *srv, struct gline *gline) {
-    char host[HOSTLEN+1], ident[USERLEN+1], *sep;
-    unsigned int len;
-    if (srv) {
-        log_module(MAIN_LOG, LOG_WARNING, "%s tried to send a targeted G-line for %s (not supported by protocol!)", gline->issuer, gline->target);
-        return;
-    }
-    if (!(sep = strchr(gline->target, '@'))) {
-        log_module(MAIN_LOG, LOG_ERROR, "%s tried to add G-line with bad mask %s", gline->issuer, gline->target);
-        return;
-    }
-    len = sep - gline->target + 1;
-    if (len > ArrayLength(ident)) len = ArrayLength(ident);
-    safestrncpy(ident, gline->target, len);
-    safestrncpy(host, sep+1, ArrayLength(host));
-    putsock(":%s AKILL %s %s "FMT_TIME_T" %s "FMT_TIME_T" :%s", self->name, host, ident, gline->expires-gline->issued, gline->issuer, gline->issued, gline->reason);
-}
-
-void
-irc_settime(UNUSED_ARG(const char *srv_name_mask), UNUSED_ARG(time_t new_time))
-{
-    /* Bahamut has nothing like this, so ignore it. */
-}
-
-void
-irc_ungline(const char *mask) {
-    char host[HOSTLEN+1], ident[USERLEN+1], *sep;
-    unsigned int len;
-    if (!(sep = strchr(mask, '@'))) {
-        log_module(MAIN_LOG, LOG_ERROR, "Tried to remove G-line with bad mask %s", mask);
-        return;
-    }
-    len = sep - mask + 1;
-    if (len > ArrayLength(ident)) len = ArrayLength(ident);
-    safestrncpy(ident, mask, len);
-    safestrncpy(host, sep+1, ArrayLength(host));
-    putsock(":%s RAKILL %s %s", self->name, host, ident);
-}
-
-void
-irc_error(const char *to, const char *message) {
-    if (to) {
-        putsock("%s ERROR :%s", to, message);
-    } else {
-        putsock(":%s ERROR :%s", self->name, message);
-    }
-}
-
-void
-irc_kill(struct userNode *from, struct userNode *target, const char *message) {
-    if (from) {
-        putsock(":%s KILL %s :%s!%s (%s)", from->nick, target->nick, self->name, from->nick, message);
-    } else {
-        putsock(":%s KILL %s :%s (%s)", self->name, target->nick, self->name, message);
-    }
-}
-
-void
-irc_raw(const char *what) {
-    putsock("%s", what);
-}
-
-void
-irc_stats(struct userNode *from, struct server *target, char type) {
-    putsock(":%s STATS %c :%s", from->nick, type, target->name);
-}
-
-void
-irc_svsnick(struct userNode *from, struct userNode *target, const char *newnick)
-{
-    putsock(":%s SVSNICK %s %s :"FMT_TIME_T, from->nick, target->nick, newnick, now);
-}
-
-void
-irc_numeric(struct userNode *user, unsigned int num, const char *format, ...) {
-    va_list arg_list;
-    char buffer[MAXLEN];
-    va_start(arg_list, format);
-    vsnprintf(buffer, MAXLEN-2, format, arg_list);
-    buffer[MAXLEN-1] = 0;
-    putsock(":%s %03d %s %s", self->name, num, user->nick, buffer);
-}
-
-static void
-parse_foreach(char *target_list, foreach_chanfunc cf, foreach_nonchan nc, foreach_userfunc uf, foreach_nonuser nu, void *data) {
-    char *j, old;
-    do {
-       j = target_list;
-       while (*j != 0 && *j != ',') j++;
-       old = *j;
-        *j = 0;
-       if (IsChannelName(target_list)) {
-           struct chanNode *chan = GetChannel(target_list);
-            if (chan) {
-                if (cf) cf(chan, data);
-            } else {
-                if (nc) nc(target_list, data);
-            }
-       } else {
-           struct userNode *user;
-            struct privmsg_desc *pd = data;
-
-            pd->is_qualified = 0;
-            if (*target_list == '@') {
-                user = NULL;
-            } else if (strchr(target_list, '@')) {
-               struct server *server;
-
-                pd->is_qualified = 1;
-               user = GetUserH(strtok(target_list, "@"));
-               server = GetServerH(strtok(NULL, "@"));
-
-               if (user && (user->uplink != server)) {
-                   /* Don't attempt to index into any arrays
-                      using a user's numeric on another server. */
-                   user = NULL;
-               }
-           } else {
-               user = GetUserH(target_list);
-           }
-
-            if (user) {
-                if (uf) uf(user, data);
-            } else {
-                if (nu) nu(target_list, data);
-            }
-       }
-       target_list = j+1;
-    } while (old == ',');
-}
-
-static CMD_FUNC(cmd_notice) {
-    struct privmsg_desc pd;
-    if ((argc < 3) || !origin) return 0;
-    if (!(pd.user = GetUserH(origin))) return 1;
-    if (IsGagged(pd.user) && !IsOper(pd.user)) return 1;
-    pd.is_notice = 1;
-    pd.text = argv[2];
-    parse_foreach(argv[1], privmsg_chan_helper, NULL, privmsg_user_helper, privmsg_invalid, &pd);
-    return 1;
-}
-
-static CMD_FUNC(cmd_privmsg) {
-    struct privmsg_desc pd;
-    if ((argc < 3) || !origin) return 0;
-    if (!(pd.user = GetUserH(origin))) return 1;
-    if (IsGagged(pd.user) && !IsOper(pd.user)) return 1;
-    pd.is_notice = 0;
-    pd.text = argv[2];
-    parse_foreach(argv[1], privmsg_chan_helper, NULL, privmsg_user_helper, privmsg_invalid, &pd);
-    return 1;
-}
-
-static CMD_FUNC(cmd_whois) {
-    struct userNode *from;
-    struct userNode *who;
-
-    if (argc < 3)
-        return 0;
-    if (!(from = GetUserH(origin))) {
-        log_module(MAIN_LOG, LOG_ERROR, "Could not find WHOIS origin user %s", origin);
-        return 0;
-    }
-    if(!(who = GetUserH(argv[2]))) {
-        irc_numeric(from, ERR_NOSUCHNICK, "%s@%s :No such nick", argv[2], self->name);
-        return 1;
-    }
-    if (IsHiddenHost(who) && !IsOper(from)) {
-        /* Just stay quiet. */
-        return 1;
-    }
-    irc_numeric(from, RPL_WHOISUSER, "%s %s %s * :%s", who->nick, who->ident, who->hostname, who->info);
-#ifdef WITH_PROTOCOL_P10
-    if (his_servername && his_servercomment)
-      irc_numeric(from, RPL_WHOISSERVER, "%s %s :%s", who->nick, his_servername, his_servercomment);
-    else
-#endif
-    irc_numeric(from, RPL_WHOISSERVER, "%s %s :%s", who->nick, who->uplink->name, who->uplink->description);
-
-    if (IsOper(who)) {
-        irc_numeric(from, RPL_WHOISOPERATOR, "%s :is a megalomaniacal power hungry tyrant", who->nick);
-    }
-    irc_numeric(from, RPL_ENDOFWHOIS, "%s :End of /WHOIS list", who->nick);
-    return 1;
-}
-
-static CMD_FUNC(cmd_capab) {
-    static const struct {
-        const char *name;
-        unsigned int mask;
-    } capabs[] = {
-        { "TS3", CAPAB_TS3 },
-        { "NOQUIT", CAPAB_NOQUIT },
-        { "SSJOIN", CAPAB_SSJOIN },
-        { "BURST", CAPAB_BURST },
-        { "UNCONNECT", CAPAB_UNCONNECT },
-        { "NICKIP", CAPAB_NICKIP },
-        { "TSMODE", CAPAB_TSMODE },
-        { "ZIP", CAPAB_ZIP },
-        { NULL, 0 }
-    };
-    unsigned int nn, mm;
-
-    uplink_capab = 0;
-    for(nn=1; nn<argc; nn++) {
-        for (mm=0; capabs[mm].name && irccasecmp(capabs[mm].name, argv[nn]); mm++) ;
-        if (capabs[mm].name) {
-            uplink_capab |= capabs[mm].mask;
-        } else {
-            log_module(MAIN_LOG, LOG_INFO, "Saw unrecognized/unhandled capability %s.  Please notify X3 developers so they can add it.", argv[nn]);
-        }
-    }
-    return 1;
-}
-
-static void burst_channel(struct chanNode *chan) {
-    char line[510];
-    int pos, base_len, len, queued;
-    unsigned int nn;
-
-    if (!chan->members.used) return;
-    /* send list of users in the channel.. */
-    base_len = sprintf(line, ":%s SJOIN "FMT_TIME_T" %s ", self->name, chan->timestamp, chan->name);
-    len = irc_make_chanmode(chan, line+base_len);
-    pos = base_len + len;
-    line[pos++] = ' ';
-    line[pos++] = ':';
-    for (nn=0; nn<chan->members.used; nn++) {
-        struct modeNode *mn = chan->members.list[nn];
-        len = strlen(mn->user->nick);
-        if (pos + len > 500) {
-            line[pos-1] = 0;
-            putsock("%s", line);
-            pos = base_len;
-            line[pos++] = '0';
-            line[pos++] = ' ';
-            line[pos++] = ':';
-        }
-        if (mn->modes & MODE_CHANOP) line[pos++] = '@';
-        if (mn->modes & MODE_VOICE) line[pos++] = '+';
-        memcpy(line+pos, mn->user->nick, len);
-        pos = pos + len;
-        line[pos++] = ' ';
-    }
-    /* print the last line */
-    line[pos] = 0;
-    putsock("%s", line);
-    /* now send the bans.. */
-    base_len = sprintf(line, ":%s MODE "FMT_TIME_T" %s +", self->name, chan->timestamp, chan->name);
-    pos = sizeof(line)-1;
-    line[pos] = 0;
-    for (nn=queued=0; nn<chan->banlist.used; nn++) {
-        struct banNode *bn = chan->banlist.list[nn];
-        len = strlen(bn->ban);
-        if (pos < base_len+queued+len+4) {
-            while (queued) {
-                line[--pos] = 'b';
-                queued--;
-            }
-            putsock("%s%s", line, line+pos);
-            pos = sizeof(line)-1;
-        }
-        pos -= len;
-        memcpy(line+pos, bn->ban, len);
-        line[--pos] = ' ';
-        queued++;
-    }
-    if (queued) {
-        while (queued) {
-            line[--pos] = 'b';
-            queued--;
-        }
-        putsock("%s%s", line, line+pos);
-    }
-}
-
-static void send_burst() {
-    dict_iterator_t it;
-    for (it = dict_first(servers); it; it = iter_next(it)) {
-        struct server *serv = iter_data(it);
-        if ((serv != self) && (serv != self->uplink)) irc_server(serv);
-    }
-    putsock("BURST");
-    for (it = dict_first(clients); it; it = iter_next(it)) {
-        irc_user(iter_data(it));
-    }
-    for (it = dict_first(channels); it; it = iter_next(it)) {
-        burst_channel(iter_data(it));
-    }
-    /* Uplink will do AWAY and TOPIC bursts before sending BURST 0, but we don't */
-    putsock("BURST 0");
-}
-
-static CMD_FUNC(cmd_server) {
-    if (argc < 4) return 0;
-    if (origin) {
-        AddServer(GetServerH(origin), argv[1], atoi(argv[2]), 0, now, 0, argv[3]);
-    } else {
-        self->uplink = AddServer(self, argv[1], atoi(argv[2]), 0, now, 0, argv[3]);
-    }
-    return 1;
-}
-
-static CMD_FUNC(cmd_svinfo) {
-    if (argc < 5) return 0;
-    if ((atoi(argv[1]) < 3) || (atoi(argv[2]) > 3)) return 0;
-    /* TODO: something with the timestamp we get from the other guy */
-    send_burst();
-    return 1;
-}
-
-static CMD_FUNC(cmd_ping)
-{
-    irc_pong(self->name, argc > 1 ? argv[1] : origin);
-    timeq_del(0, timed_send_ping, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
-    timeq_del(0, timed_ping_timeout, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
-    timeq_add(now + ping_freq, timed_send_ping, 0);
-    received_ping();
-    return 1;
-}
-
-static CMD_FUNC(cmd_burst) {
-    struct server *sender = GetServerH(origin);
-    if (!sender) return 0;
-    if (argc == 1) return 1;
-    if (sender == self->uplink) {
-        cManager.uplink->state = CONNECTED;
-    }
-    sender->self_burst = 0;
-    recalc_bursts(sender);
-    return 1;
-}
-
-static CMD_FUNC(cmd_nick) {
-    struct userNode *un;
-    if ((un = GetUserH(origin))) {
-        /* nick change */
-        if (argc < 2) return 0;
-        NickChange(un, argv[1], 1);
-    } else {
-        /* new nick from a server */
-        char id[8];
-        unsigned long stamp;
-        irc_in_addr_t ip;
-
-        if (argc < 10) return 0;
-        stamp = strtoul(argv[8], NULL, 0);
-        if (stamp) inttobase64(id, stamp, IDLEN);
-        if (argc > 10)
-            ip.in6_32[3] = htonl(atoi(argv[9]));
-        un = AddUser(GetServerH(argv[7]), argv[1], argv[5], argv[6], argv[4], argv[argc-1], atoi(argv[3]), ip, (stamp ? id : 0));
-    }
-    return 1;
-}
-
-static CMD_FUNC(cmd_sjoin) {
-    struct chanNode *cNode;
-    struct userNode *uNode;
-    struct modeNode *mNode;
-    unsigned int next = 4, last;
-    char *nick, *nickend;
-
-    if ((argc == 3) && (uNode = GetUserH(origin))) {
-        /* normal JOIN */
-        if (!(cNode = GetChannel(argv[2]))) {
-            log_module(MAIN_LOG, LOG_ERROR, "Unable to find SJOIN target %s", argv[2]);
-            return 0;
-        }
-        AddChannelUser(uNode, cNode);
-        return 1;
-    }
-    if (argc < 5) return 0;
-    if (argv[3][0] == '+') {
-        char modes[MAXLEN], *pos;
-        int n_modes;
-        for (pos = argv[3], n_modes = 1; *pos; pos++) {
-            if ((*pos == 'k') || (*pos == 'l')) n_modes++;
-        }
-        unsplit_string(argv+3, n_modes, modes);
-        cNode = AddChannel(argv[2], atoi(argv[1]), modes, NULL);
-    } else if (argv[3][0] == '0') {
-        cNode = GetChannel(argv[2]);
-    } else {
-        log_module(MAIN_LOG, LOG_ERROR, "Unsure how to handle SJOIN when arg 3 is %s", argv[3]);
-        return 0;
-    }
-
-    /* argv[next] is now the space-delimited, @+-prefixed list of
-     * nicks in the channel.  Split it and add the users. */
-    for (last = 0, nick = argv[next]; !last; nick = nickend + 1) {
-        int mode = 0;
-        for (nickend = nick; *nickend && (*nickend != ' '); nickend++) ;
-        if (!*nickend) last = 1;
-        *nickend = 0;
-        if (*nick == '@') { mode |= MODE_CHANOP; nick++; }
-        if (*nick == '+') { mode |= MODE_VOICE; nick++; }
-        if ((uNode = GetUserH(nick)) && (mNode = AddChannelUser(uNode, cNode))) {
-            mNode->modes = mode;
-        }
-    }
-    return 1;
-}
-
-static CMD_FUNC(cmd_mode) {
-    struct userNode *un;
-
-    if (argc < 2) {
-        log_module(MAIN_LOG, LOG_ERROR, "Illegal MODE from %s (no arguments).", origin);
-        return 0;
-    } else if (IsChannelName(argv[1])) {
-        struct chanNode *cn;
-        struct modeNode *mn;
-
-        if (!(cn = GetChannel(argv[1]))) {
-            log_module(MAIN_LOG, LOG_ERROR, "Unable to find channel %s whose mode is changing", argv[1]);
-            return 0;
-        }
-
-        if ((un = GetUserH(origin))) {
-            /* Update idle time for the user */
-            if ((mn = GetUserMode(cn, un)))
-                mn->idle_since = now;
-        } else {
-            /* Must be a server in burst or something.  Make sure we're using the right timestamp. */
-            cn->timestamp = atoi(argv[2]);
-        }
-
-        return mod_chanmode(un, cn, argv+3, argc-3, MCP_ALLOW_OVB|MCP_FROM_SERVER|MC_ANNOUNCE);
-    } else if ((un = GetUserH(argv[1]))) {
-        mod_usermode(un, argv[2]);
-        return 1;
-    } else {
-        log_module(MAIN_LOG, LOG_ERROR, "Not sure what MODE %s is affecting (not a channel name and no such user)", argv[1]);
-        return 0;
-    }
-}
-
-static CMD_FUNC(cmd_topic) {
-    struct chanNode *cn;
-    if (argc < 5) return 0;
-    if (!(cn = GetChannel(argv[1]))) {
-        log_module(MAIN_LOG, LOG_ERROR, "Unable to find channel %s whose topic is being set", argv[1]);
-        return 0;
-    }
-    if (irccasecmp(origin, argv[2])) {
-        /* coming from a topic burst; the origin is a server */
-        safestrncpy(cn->topic, argv[4], sizeof(cn->topic));
-        safestrncpy(cn->topic_nick, argv[2], sizeof(cn->topic_nick));
-        cn->topic_time = atoi(argv[3]);
-    } else {
-        SetChannelTopic(cn, GetUserH(argv[2]), argv[4], 0);
-    }
-    return 1;
-}
-
-static CMD_FUNC(cmd_part) {
-    if (argc < 2) return 0;
-    parse_foreach(argv[1], part_helper, NULL, NULL, NULL, GetUserH(origin));
-    return 1;
-}
-
-static CMD_FUNC(cmd_away) {
-    struct userNode *un;
-
-    if (!(un = GetUserH(origin))) {
-        log_module(MAIN_LOG, LOG_ERROR, "Unable to find user %s sending AWAY", origin);
-        return 0;
-    }
-    if (argc > 1) {
-        un->modes |= FLAGS_AWAY;
-    } else {
-        un->modes &= ~FLAGS_AWAY;
-    }
-    return 1;
-}
-
-static CMD_FUNC(cmd_kick) {
-    if (argc < 3) return 0;
-    ChannelUserKicked(GetUserH(origin), GetUserH(argv[2]), GetChannel(argv[1]));
-    return 1;
-}
-
-static CMD_FUNC(cmd_kill) {
-    struct userNode *user;
-    if (argc < 3) return 0;
-    if (!(user = GetUserH(argv[1]))) {
-        log_module(MAIN_LOG, LOG_ERROR, "Unable to find kill victim %s", argv[1]);
-        return 0;
-    }
-    if (IsLocal(user) && IsService(user)) {
-        ReintroduceUser(user);
-    } else {
-        DelUser(user, GetUserH(origin), false, ((argc >= 3) ? argv[2] : NULL));
-    }
-    return 1;
-}
-
-static CMD_FUNC(cmd_pong)
-{
-    if (argc < 3) return 0;
-    if (!strcmp(argv[2], self->name)) {
-       timeq_del(0, timed_send_ping, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
-       timeq_del(0, timed_ping_timeout, 0, TIMEQ_IGNORE_WHEN|TIMEQ_IGNORE_DATA);
-       timeq_add(now + ping_freq, timed_send_ping, 0);
-       received_ping();
-    }
-    return 1;
-}
-
-static CMD_FUNC(cmd_num_topic)
-{
-    static struct chanNode *cn;
-
-    if (!argv[0])
-        return 0; /* huh? */
-    if (argv[2]) {
-        cn = GetChannel(argv[2]);
-        if (!cn) {
-            log_module(MAIN_LOG, LOG_ERROR, "Unable to find channel %s in topic reply", argv[2]);
-            return 0;
-        }
-    } else
-        return 0;
-
-    switch (atoi(argv[0])) {
-    case 331:
-        cn->topic_time = 0;
-        break;  /* no topic */
-    case 332:
-        if (argc < 4)
-            return 0;
-        safestrncpy(cn->topic, unsplit_string(argv+3, argc-3, NULL), sizeof(cn->topic));
-        break;
-    case 333:
-        if (argc < 5)
-            return 0;
-        safestrncpy(cn->topic_nick, argv[3], sizeof(cn->topic_nick));
-        cn->topic_time = atoi(argv[4]);
-        break;
-    default:
-        return 0; /* should never happen */
-    }
-    return 1;
-}
-
-static CMD_FUNC(cmd_quit)
-{
-    struct userNode *user;
-    if (argc < 2) return 0;
-    /* Sometimes we get a KILL then a QUIT or the like, so we don't want to
-     * call DelUser unless we have the user in our grasp. */
-    if ((user = GetUserH(origin))) {
-        DelUser(user, NULL, false, argv[1]);
-    }
-    return 1;
-}
-
-static CMD_FUNC(cmd_squit)
-{
-    struct server *server;
-    if (argc < 3)
-        return 0;
-    if (!(server = GetServerH(argv[1])))
-        return 0;
-    if (server == self->uplink) {
-        /* Force a reconnect to the currently selected server. */
-        cManager.uplink->tries = 0;
-        log_module(MAIN_LOG, LOG_INFO, "Squitting from uplink: %s", argv[3]);
-        close_socket();
-        return 1;
-    }
-
-    DelServer(server, 0, argv[3]);
-    return 1;
-}
-
-static CMD_FUNC(cmd_svsnick)
-{
-    struct userNode *target, *dest;
-    if (argc < 4) return 0;
-    if (!(target = GetUserH(argv[1]))) return 0;
-    if (!IsLocal(target)) return 0;
-    if ((dest = GetUserH(argv[2]))) return 0; /* Note: Bahamut will /KILL instead. */
-    NickChange(target, argv[2], 0);
-    return 1;
-}
-
-static oper_func_t *of_list;
-static unsigned int of_size = 0, of_used = 0;
-
-void parse_cleanup(void) {
-    unsigned int nn;
-    if (of_list) free(of_list);
-    dict_delete(irc_func_dict);
-    dict_delete(service_msginfo_dict);
-    free(mcf_list);
-    for (nn=0; nn<dead_users.used; nn++) free_user(dead_users.list[nn]);
-    userList_clean(&dead_users);
-}
-
-void init_parse(void) {
-    const char *str, *desc;
-
-    str = conf_get_data("server/ping_freq", RECDB_QSTRING);
-    ping_freq = str ? ParseInterval(str) : 120;
-    str = conf_get_data("server/ping_timeout", RECDB_QSTRING);
-    ping_timeout = str ? ParseInterval(str) : 30;
-    str = conf_get_data("server/hostname", RECDB_QSTRING);
-    desc = conf_get_data("server/description", RECDB_QSTRING);
-    if (!str || !desc) {
-        log_module(MAIN_LOG, LOG_ERROR, "No server/hostname entry in config file.");
-        exit(1);
-    }
-    self = AddServer(NULL, str, 0, boot_time, now, NULL, desc);
-
-    str = conf_get_data("server/ping_freq", RECDB_QSTRING);
-    ping_freq = str ? ParseInterval(str) : 120;
-    str = conf_get_data("server/ping_timeout", RECDB_QSTRING);
-    ping_timeout = str ? ParseInterval(str) : 30;
-
-    service_msginfo_dict = dict_new();
-    dict_set_free_data(service_msginfo_dict, free);
-    irc_func_dict = dict_new();
-    dict_insert(irc_func_dict, "ADMIN", cmd_admin);
-    dict_insert(irc_func_dict, "AWAY", cmd_away);
-    dict_insert(irc_func_dict, "BURST", cmd_burst);
-    dict_insert(irc_func_dict, "CAPAB", cmd_capab);
-    dict_insert(irc_func_dict, "ERROR", cmd_error);
-    dict_insert(irc_func_dict, "GNOTICE", cmd_dummy);
-    dict_insert(irc_func_dict, "INVITE", cmd_dummy);
-    dict_insert(irc_func_dict, "KICK", cmd_kick);
-    dict_insert(irc_func_dict, "KILL", cmd_kill);
-    dict_insert(irc_func_dict, "LUSERSLOCK", cmd_dummy);
-    dict_insert(irc_func_dict, "MODE", cmd_mode);
-    dict_insert(irc_func_dict, "NICK", cmd_nick);
-    dict_insert(irc_func_dict, "NOTICE", cmd_notice);
-    dict_insert(irc_func_dict, "PART", cmd_part);
-    dict_insert(irc_func_dict, "PASS", cmd_pass);
-    dict_insert(irc_func_dict, "PING", cmd_ping);
-    dict_insert(irc_func_dict, "PONG", cmd_pong);
-    dict_insert(irc_func_dict, "PRIVMSG", cmd_privmsg);
-    dict_insert(irc_func_dict, "QUIT", cmd_quit);
-    dict_insert(irc_func_dict, "SERVER", cmd_server);
-    dict_insert(irc_func_dict, "SJOIN", cmd_sjoin);
-    dict_insert(irc_func_dict, "SQUIT", cmd_squit);
-    dict_insert(irc_func_dict, "STATS", cmd_stats);
-    dict_insert(irc_func_dict, "SVSNICK", cmd_svsnick);
-    dict_insert(irc_func_dict, "SVINFO", cmd_svinfo);
-    dict_insert(irc_func_dict, "TOPIC", cmd_topic);
-    dict_insert(irc_func_dict, "VERSION", cmd_version);
-    dict_insert(irc_func_dict, "WHOIS", cmd_whois);
-    dict_insert(irc_func_dict, "331", cmd_num_topic);
-    dict_insert(irc_func_dict, "332", cmd_num_topic);
-    dict_insert(irc_func_dict, "333", cmd_num_topic);
-    dict_insert(irc_func_dict, "413", cmd_num_topic);
-
-    userList_init(&dead_users);
-    reg_exit_func(parse_cleanup);
-}
-
-int parse_line(char *line, int recursive) {
-    char *argv[MAXNUMPARAMS];
-    int argc, cmd, res;
-    cmd_func_t *func;
-
-    argc = split_line(line, true, ArrayLength(argv), argv);
-    cmd = line[0] == ':';
-    if ((argc > cmd) && (func = dict_find(irc_func_dict, argv[cmd], NULL))) {
-        char *origin;
-        if (cmd) {
-            origin = argv[0] + 1;
-        } else if (self->uplink) {
-            origin = self->uplink->name;
-        } else {
-            origin = NULL;
-        }
-        res = func(origin, argc-cmd, argv+cmd);
-    } else {
-        res = 0;
-    }
-    if (!res) {
-       log_module(MAIN_LOG, LOG_ERROR, "PARSE ERROR on line: %s", unsplit_string(argv, argc, NULL));
-    } else if (!recursive) {
-        unsigned int i;
-        for (i=0; i<dead_users.used; i++) {
-            free_user(dead_users.list[i]);
-        }
-        dead_users.used = 0;
-    }
-    return res;
-}
-
-static void
-privmsg_user_helper(struct userNode *un, void *data)
-{
-    struct privmsg_desc *pd = data;
-    struct service_message_info *info = dict_find(service_msginfo_dict, un->nick, 0);
-    if (info) {
-        if (pd->is_notice) {
-            if (info->on_notice) info->on_notice(pd->user, un, pd->text, pd->is_qualified);
-        } else {
-            if (info->on_privmsg) info->on_privmsg(pd->user, un, pd->text, pd->is_qualified);
-        }
-    }
-}
-
-void
-reg_privmsg_func(struct userNode *user, privmsg_func_t handler) {
-    struct service_message_info *info = dict_find(service_msginfo_dict, user->nick, NULL);
-    if (!info) {
-        info = calloc(1, sizeof(*info));
-        dict_insert(service_msginfo_dict, user->nick, info);
-    }
-    info->on_privmsg = handler;
-}
-
-void
-reg_notice_func(struct userNode *user, privmsg_func_t handler) {
-    struct service_message_info *info = dict_find(service_msginfo_dict, user->nick, NULL);
-    if (!info) {
-        info = calloc(1, sizeof(*info));
-        dict_insert(service_msginfo_dict, user->nick, info);
-    }
-    info->on_notice = handler;
-}
-
-void
-reg_oper_func(oper_func_t handler)
-{
-    if (of_used == of_size) {
-       if (of_size) {
-           of_size <<= 1;
-           of_list = realloc(of_list, of_size*sizeof(oper_func_t));
-       } else {
-           of_size = 8;
-           of_list = malloc(of_size*sizeof(oper_func_t));
-       }
-    }
-    of_list[of_used++] = handler;
-}
-
-static void
-call_oper_funcs(struct userNode *user)
-{
-    unsigned int n;
-    if (IsLocal(user)) return;
-    for (n=0; n<of_used; n++)
-    {
-       of_list[n](user);
-    }
-}
-
-void mod_usermode(struct userNode *user, const char *mode_change) {
-    int add = 1;
-
-    if (!user || !mode_change) return;
-    while (1) {
-#define do_user_mode(FLAG) do { if (add) user->modes |= FLAG; else user->modes &= ~FLAG; } while (0)
-       switch (*mode_change++) {
-       case 0: return;
-       case '+': add = 1; break;
-       case '-': add = 0; break;
-       case 'o':
-           do_user_mode(FLAGS_OPER);
-           if (add) {
-               userList_append(&curr_opers, user);
-               call_oper_funcs(user);
-           } else {
-               userList_remove(&curr_opers, user);
-           }
-           break;
-       case 'O': do_user_mode(FLAGS_LOCOP); break;
-       case 'i': do_user_mode(FLAGS_INVISIBLE);
-           if (add) invis_clients++; else invis_clients--;
-           break;
-       case 'w': do_user_mode(FLAGS_WALLOP); break;
-       case 's': do_user_mode(FLAGS_SERVNOTICE); break;
-       case 'd': do_user_mode(FLAGS_DEAF); break;
-       case 'r': do_user_mode(FLAGS_REGNICK); break;
-       case 'k': do_user_mode(FLAGS_SERVICE); break;
-       case 'g': do_user_mode(FLAGS_GLOBAL); break;
-       case 'h': do_user_mode(FLAGS_HELPER); break;
-       }
-#undef do_user_mode
-    }
-}
-
-struct mod_chanmode *
-mod_chanmode_parse(struct chanNode *channel, char **modes, unsigned int argc, unsigned int flags, short base_oplevel)
-{
-    struct mod_chanmode *change;
-    unsigned int ii, in_arg, ch_arg, add;
-
-    if (argc == 0)
-        return NULL;
-    if (!(change = mod_chanmode_alloc(argc)))
-        return NULL;
-
-    for (ii = ch_arg = 0, in_arg = add = 1;
-         (modes[0][ii] != '\0') && (modes[0][ii] != ' ');
-         ++ii) {
-        switch (modes[0][ii]) {
-        case '+':
-            add = 1;
-            break;
-        case '-':
-            add = 0;
-            break;
-#define do_chan_mode(FLAG) do { if (add) change->modes_set |= FLAG, change->modes_clear &= ~FLAG; else change->modes_clear |= FLAG, change->modes_set &= ~FLAG; } while(0)
-        case 'R': do_chan_mode(MODE_REGONLY); break;
-        case 'D': do_chan_mode(MODE_DELAYJOINS); break;
-        case 'c': do_chan_mode(MODE_NOCOLORS); break;
-        case 'i': do_chan_mode(MODE_INVITEONLY); break;
-        case 'm': do_chan_mode(MODE_MODERATED); break;
-        case 'n': do_chan_mode(MODE_NOPRIVMSGS); break;
-        case 'p': do_chan_mode(MODE_PRIVATE); break;
-        case 's': do_chan_mode(MODE_SECRET); break;
-        case 't': do_chan_mode(MODE_TOPICLIMIT); break;
-       case 'r':
-           if (!(flags & MCP_REGISTERED)) {
-            do_chan_mode(MODE_REGISTERED);
-           } else {
-            mod_chanmode_free(change);
-            return NULL;
-           }
-           break;
-#undef do_chan_mode
-        case 'l':
-            if (add) {
-                if (in_arg >= argc)
-                    goto error;
-                change->modes_set |= MODE_LIMIT;
-                change->new_limit = atoi(modes[in_arg++]);
-            } else {
-                change->modes_clear |= MODE_LIMIT;
-            }
-            break;
-        case 'k':
-            if (add) {
-                if (in_arg >= argc)
-                    goto error;
-                change->modes_set |= MODE_KEY;
-                safestrncpy(change->new_key, modes[in_arg++], sizeof(change->new_key));
-            } else {
-                change->modes_clear |= MODE_KEY;
-                if (!(flags & MCP_KEY_FREE)) {
-                    if (in_arg >= argc)
-                        goto error;
-                    in_arg++;
-                }
-            }
-            break;
-        case 'b':
-            if (!(flags & MCP_ALLOW_OVB))
-                goto error;
-            if (in_arg >= argc)
-                goto error;
-            change->args[ch_arg].mode = MODE_BAN;
-            if (!add)
-                change->args[ch_arg].mode |= MODE_REMOVE;
-            change->args[ch_arg++].u.hostmask = modes[in_arg++];
-            break;
-        case 'o': case 'v':
-        {
-            struct userNode *victim;
-            if (!(flags & MCP_ALLOW_OVB))
-                goto error;
-            if (in_arg >= argc)
-                goto error;
-            change->args[ch_arg].mode = (modes[0][ii] == 'o') ? MODE_CHANOP : MODE_VOICE;
-            if (!add)
-                change->args[ch_arg].mode |= MODE_REMOVE;
-            victim = GetUserH(modes[in_arg++]);
-            if (!victim)
-                continue;
-            if ((change->args[ch_arg].u.member = GetUserMode(channel, victim)))
-                ch_arg++;
-            break;
-        }
-        default:
-            if (!(flags & MCP_FROM_SERVER))
-                goto error;
-            break;
-        }
-    }
-    change->argc = ch_arg; /* in case any turned out to be ignored */
-    if (change->modes_set & MODE_SECRET) {
-        change->modes_set &= ~(MODE_PRIVATE);
-        change->modes_clear |= MODE_PRIVATE;
-    } else if (change->modes_set & MODE_PRIVATE) {
-        change->modes_set &= ~(MODE_SECRET);
-        change->modes_clear |= MODE_SECRET;
-    }
-    return change;
-  error:
-    mod_chanmode_free(change);
-    return NULL;
-    (void)base_oplevel;
-}
-
-struct chanmode_buffer {
-    char modes[MAXLEN];
-    char args[MAXLEN];
-    struct chanNode *channel;
-    struct userNode *actor;
-    unsigned int modes_used;
-    unsigned int args_used;
-    size_t chname_len;
-    unsigned int is_add : 1;
-};
-
-static void
-mod_chanmode_append(struct chanmode_buffer *buf, char ch, const char *arg)
-{
-    size_t arg_len = strlen(arg);
-    if (buf->modes_used + buf->args_used + buf->chname_len + arg_len > 450) {
-        memcpy(buf->modes + buf->modes_used, buf->args, buf->args_used);
-        buf->modes[buf->modes_used + buf->args_used] = '\0';
-        irc_mode(buf->actor, buf->channel, buf->modes);
-        buf->modes[0] = buf->is_add ? '+' : '-';
-        buf->modes_used = 1;
-        buf->args_used = 0;
-    }
-    buf->modes[buf->modes_used++] = ch;
-    buf->args[buf->args_used++] = ' ';
-    memcpy(buf->args + buf->args_used, arg, arg_len);
-    buf->args_used += arg_len;
-}
-
-void
-mod_chanmode_announce(struct userNode *who, struct chanNode *channel, struct mod_chanmode *change)
-{
-    struct chanmode_buffer chbuf;
-    char int_buff[32];
-    unsigned int arg;
-
-    assert(change->argc <= change->alloc_argc);
-    memset(&chbuf, 0, sizeof(chbuf));
-    chbuf.channel = channel;
-    chbuf.actor = who;
-    chbuf.chname_len = strlen(channel->name);
-
-    /* First remove modes */
-    chbuf.is_add = 0;
-    if (change->modes_clear) {
-        chbuf.modes[chbuf.modes_used++] = '-';
-#define DO_MODE_CHAR(BIT, CHAR) if (change->modes_clear & MODE_##BIT) chbuf.modes[chbuf.modes_used++] = CHAR;
-        DO_MODE_CHAR(PRIVATE, 'p');
-        DO_MODE_CHAR(SECRET, 's');
-        DO_MODE_CHAR(MODERATED, 'm');
-        DO_MODE_CHAR(TOPICLIMIT, 't');
-        DO_MODE_CHAR(INVITEONLY, 'i');
-        DO_MODE_CHAR(NOPRIVMSGS, 'n');
-        DO_MODE_CHAR(LIMIT, 'l');
-        DO_MODE_CHAR(DELAYJOINS, 'D');
-        DO_MODE_CHAR(REGONLY, 'R');
-        DO_MODE_CHAR(NOCOLORS, 'c');
-        DO_MODE_CHAR(REGISTERED, 'r');
-#undef DO_MODE_CHAR
-        if (change->modes_clear & channel->modes & MODE_KEY)
-            mod_chanmode_append(&chbuf, 'k', channel->key);
-    }
-    for (arg = 0; arg < change->argc; ++arg) {
-        if (!(change->args[arg].mode & MODE_REMOVE))
-            continue;
-        switch (change->args[arg].mode & ~MODE_REMOVE) {
-        case MODE_BAN:
-            mod_chanmode_append(&chbuf, 'b', change->args[arg].u.hostmask);
-            break;
-        default:
-            if (change->args[arg].mode & MODE_CHANOP)
-                mod_chanmode_append(&chbuf, 'o', change->args[arg].u.member->user->nick);
-            if (change->args[arg].mode & MODE_VOICE)
-                mod_chanmode_append(&chbuf, 'v', change->args[arg].u.member->user->nick);
-            break;
-        }
-    }
-
-    /* Then set them */
-    chbuf.is_add = 1;
-    if (change->modes_set) {
-        chbuf.modes[chbuf.modes_used++] = '+';
-#define DO_MODE_CHAR(BIT, CHAR) if (change->modes_set & MODE_##BIT) chbuf.modes[chbuf.modes_used++] = CHAR;
-        DO_MODE_CHAR(PRIVATE, 'p');
-        DO_MODE_CHAR(SECRET, 's');
-        DO_MODE_CHAR(MODERATED, 'm');
-        DO_MODE_CHAR(TOPICLIMIT, 't');
-        DO_MODE_CHAR(INVITEONLY, 'i');
-        DO_MODE_CHAR(NOPRIVMSGS, 'n');
-        DO_MODE_CHAR(DELAYJOINS, 'D');
-        DO_MODE_CHAR(REGONLY, 'R');
-        DO_MODE_CHAR(NOCOLORS, 'c');
-        DO_MODE_CHAR(REGISTERED, 'r');
-#undef DO_MODE_CHAR
-        if (change->modes_set & MODE_KEY)
-            mod_chanmode_append(&chbuf, 'k', change->new_key);
-        if (change->modes_set & MODE_LIMIT)
-        {
-            sprintf(int_buff, "%d", change->new_limit);
-            mod_chanmode_append(&chbuf, 'l', int_buff);
-        }
-    }
-    for (arg = 0; arg < change->argc; ++arg) {
-        if (change->args[arg].mode & MODE_REMOVE)
-            continue;
-        switch (change->args[arg].mode) {
-        case MODE_BAN:
-            mod_chanmode_append(&chbuf, 'b', change->args[arg].u.hostmask);
-            break;
-        default:
-            if (change->args[arg].mode & MODE_CHANOP)
-                mod_chanmode_append(&chbuf, 'o', change->args[arg].u.member->user->nick);
-            if (change->args[arg].mode & MODE_VOICE)
-                mod_chanmode_append(&chbuf, 'v', change->args[arg].u.member->user->nick);
-            break;
-        }
-    }
-
-    /* Flush the buffer and apply changes locally */
-    if (chbuf.modes_used > 0) {
-        memcpy(chbuf.modes + chbuf.modes_used, chbuf.args, chbuf.args_used);
-        chbuf.modes[chbuf.modes_used + chbuf.args_used] = '\0';
-        irc_mode(chbuf.actor, chbuf.channel, chbuf.modes);
-    }
-    mod_chanmode_apply(who, channel, change);
-}
-
-char *
-mod_chanmode_format(struct mod_chanmode *change, char *outbuff)
-{
-    unsigned int used = 0;
-    assert(change->argc <= change->alloc_argc);
-    if (change->modes_clear) {
-        outbuff[used++] = '-';
-#define DO_MODE_CHAR(BIT, CHAR) if (change->modes_clear & MODE_##BIT) outbuff[used++] = CHAR
-        DO_MODE_CHAR(PRIVATE, 'p');
-        DO_MODE_CHAR(SECRET, 's');
-        DO_MODE_CHAR(MODERATED, 'm');
-        DO_MODE_CHAR(TOPICLIMIT, 't');
-        DO_MODE_CHAR(INVITEONLY, 'i');
-        DO_MODE_CHAR(NOPRIVMSGS, 'n');
-        DO_MODE_CHAR(LIMIT, 'l');
-        DO_MODE_CHAR(KEY, 'k');
-        DO_MODE_CHAR(DELAYJOINS, 'D');
-        DO_MODE_CHAR(REGONLY, 'R');
-        DO_MODE_CHAR(NOCOLORS, 'c');
-        DO_MODE_CHAR(REGISTERED, 'r');
-#undef DO_MODE_CHAR
-    }
-    if (change->modes_set) {
-        outbuff[used++] = '+';
-#define DO_MODE_CHAR(BIT, CHAR) if (change->modes_set & MODE_##BIT) outbuff[used++] = CHAR
-        DO_MODE_CHAR(PRIVATE, 'p');
-        DO_MODE_CHAR(SECRET, 's');
-        DO_MODE_CHAR(MODERATED, 'm');
-        DO_MODE_CHAR(TOPICLIMIT, 't');
-        DO_MODE_CHAR(INVITEONLY, 'i');
-        DO_MODE_CHAR(NOPRIVMSGS, 'n');
-        DO_MODE_CHAR(DELAYJOINS, 'D');
-        DO_MODE_CHAR(REGONLY, 'R');
-        DO_MODE_CHAR(NOCOLORS, 'c');
-        DO_MODE_CHAR(REGISTERED, 'r');
-#undef DO_MODE_CHAR
-        switch (change->modes_set & (MODE_KEY|MODE_LIMIT)) {
-        case MODE_KEY|MODE_LIMIT:
-            used += sprintf(outbuff+used, "lk %d %s", change->new_limit, change->new_key);
-            break;
-        case MODE_KEY:
-            used += sprintf(outbuff+used, "k %s", change->new_key);
-            break;
-        case MODE_LIMIT:
-            used += sprintf(outbuff+used, "l %d", change->new_limit);
-            break;
-        }
-    }
-    outbuff[used] = 0;
-    return outbuff;
-}
index 238a12bf68f48c478c2e517ab7273763225540ce..b50bdf699d09193dcf9a6a194f5ca36c7f01a5f3 100644 (file)
@@ -122,12 +122,6 @@ shun_remove(const char *target, int announce)
             timeq_add(new_first->expires, shun_expire, 0);
         }
     }
-#ifdef WITH_PROTOCOL_BAHAMUT
-    /* Bahamut is sort of lame: It permanently remembers any AKILLs
-     * with durations longer than a day, and will never auto-expire
-     * them.  So when the time comes, we'd better remind it.  */
-    announce = 1;
-#endif
     if (announce)
         irc_unshun(target);
     return res;
index 2f47a38e83653f64c38b6fccb7f5458263ca0cbb..83ae1b7498be7aec02f5a3a011a9f3d591a481d4 100644 (file)
 
             // What to do when someone uses the NickServ "reclaim" command?
             // This can be one of "none", "warn", "svsnick", or "kill", but
-            // stock ircu does not support svsnick -- you need Bahamut or 
-            // nefarious.
+            // stock ircu does not support svsnick -- you need nefarious.
             "reclaim_action" "none";
 
             // What (else) to do when someone uses a registered nick?