diff -bBuNrd csircd-1.14.vanilla/include/hash.h csircd-1.14/include/hash.h --- csircd-1.14.vanilla/include/hash.h 2001-09-30 12:35:38.000000000 +0200 +++ csircd-1.14/include/hash.h 2003-09-11 03:55:31.000000000 +0200 @@ -50,6 +50,10 @@ void del_invite_from_list(IRCD_INVITE **bucket, IRCD_INVITE *invite); void add_ban_to_list(IRCD_BAN **bucket, IRCD_BAN *ban); void del_ban_from_list(IRCD_BAN **bucket, IRCD_BAN *ban); +void add_except_to_list(IRCD_EXCEPT **bucket, IRCD_BAN *except); +void del_execpt_from_list(IRCD_EXCEPT **bucket, IRCD_BAN *except); +void add_invex_to_list(IRCD_INVEX **bucket, IRCD_BAN *invex); +void del_invex_from_list(IRCD_INVEX **bucket, IRCD_BAN *invex); void add_reqlist_to_list(IRCDRES_REQLIST **bucket, IRCDRES_REQLIST *reqlist); void del_reqlist_from_list(IRCDRES_REQLIST **bucket, IRCDRES_REQLIST *reqlist); int hash_init_reload(void **client_hash, int client_hash_size, void **channel_hash, int channel_hash_size); diff -bBuNrd csircd-1.14.vanilla/include/numeric.h csircd-1.14/include/numeric.h --- csircd-1.14.vanilla/include/numeric.h 2003-02-04 10:28:28.000000000 +0100 +++ csircd-1.14/include/numeric.h 2003-09-11 03:51:39.000000000 +0200 @@ -82,6 +82,10 @@ #define RPL_TOPICWHOTIME 333 #define RPL_INVITING 341 #define RPL_SUMMONING 342 +#define RPL_INVEXLIST 346 +#define RPL_ENDOFINVEXLIST 347 +#define RPL_EXCEPTLIST 348 +#define RPL_ENDOFEXCEPTLIST 349 #define RPL_VERSION 351 #define RPL_WHOREPLY 352 #define RPL_NAMREPLY 353 diff -bBuNrd csircd-1.14.vanilla/include/structs.h csircd-1.14/include/structs.h --- csircd-1.14.vanilla/include/structs.h 2003-03-17 09:53:24.000000000 +0100 +++ csircd-1.14/include/structs.h 2003-09-11 04:26:52.000000000 +0200 @@ -20,6 +20,8 @@ typedef struct _ircd_client IRCD_CLIENT; typedef struct _ircd_whowas IRCD_WHOWAS; typedef struct _ircd_ban IRCD_BAN; +typedef struct _ircd_except IRCD_EXCEPT; +typedef struct _ircd_invex IRCD_INVEX; typedef struct _ircd_channel IRCD_CHANNEL; typedef struct _ircd_channellist IRCD_CHANNELLIST; typedef struct _ircd_clientlist IRCD_CLIENTLIST; @@ -475,6 +477,7 @@ #define IRCD_CAPAB_VALUE_KLINE 0x040 #define IRCD_CAPAB_VALUE_UNKLINE 0x080 #define IRCD_CAPAB_VALUE_ENCAP 0x100 +#define IRCD_CAPAB_VALUE_IMODE 0x200 #define IsCapable(__x, __y) ((__x)->c_capab_flags & (__y)) int c_capab_flags; @@ -511,6 +514,29 @@ IRCD_BAN *next; IRCD_BAN *prev; }; +struct _ircd_except +{ + char *exceptstring; + char *who; + int excepttime; + char *firstpart; + ircd_uint32_t net; + ircd_uint32_t mask; + IRCD_BAN *next; + IRCD_BAN *prev; +}; + +struct _ircd_invex +{ + char *invexstring; + char *who; + int invextime; + char *firstpart; + ircd_uint32_t net; + ircd_uint32_t mask; + IRCD_BAN *next; + IRCD_BAN *prev; +}; struct _ircd_channel { @@ -542,6 +568,8 @@ int nbans; IRCD_BAN *bans; + IRCD_INVEX *invexs; + IRCD_EXCEPT *excepts; IRCD_CHANNEL *prev; IRCD_CHANNEL *next; diff -bBuNrd csircd-1.14.vanilla/lib/commands.c csircd-1.14/lib/commands.c --- csircd-1.14.vanilla/lib/commands.c 2003-03-17 09:53:26.000000000 +0100 +++ csircd-1.14/lib/commands.c 2003-09-11 06:26:48.000000000 +0200 @@ -103,6 +103,11 @@ static char *_make_nick_user_host(char *nick, char *user, char *host, char *buf, char **hostptr); static int _channel_ban_add(IRCD_CHANNEL *chptr, IRCD_CLIENT *pptr, char *str, char *hostptr, ircd_uint32_t net, ircd_uint32_t mask); static int _channel_ban_del(IRCD_CHANNEL *chptr, char *str); +static int _channel_invex_add(IRCD_CHANNEL *chptr, IRCD_CLIENT *pptr, char *str, char *hostptr, ircd_uint32_t net, ircd_uint32_t mask); +static int _channel_invex_del(IRCD_CHANNEL *chptr, char *str); +static int _channel_except_add(IRCD_CHANNEL *chptr, IRCD_CLIENT *pptr, char *str, char *hostptr, ircd_uint32_t net, ircd_uint32_t mask); +static int _channel_except_del(IRCD_CHANNEL *chptr, char *str); + static void do_who(IRCD_CLIENT *pptr, IRCD_CLIENT *acptr, IRCD_CHANNEL *chptr, IRCD_CLIENTLIST *clptr); static char *datestr(int thetime, char *buf); static char *_cluster(char *hostname); @@ -168,14 +173,15 @@ #if 0 { IRCD_CAPAB_VALUE_IPADDR, "IPADDR", 0 }, { IRCD_CAPAB_VALUE_ZIP, "ZIP", 0 }, - { IRCD_CAPAB_VALUE_EMODE, "EX", 0 }, #endif + { IRCD_CAPAB_VALUE_EMODE, "EX", 0 }, { IRCD_CAPAB_VALUE_NOQUITSTORM, "QS", 0 }, { IRCD_CAPAB_VALUE_WALLCHOPS, "CHW", 0 }, { IRCD_CAPAB_VALUE_GLINES, "GLN", 0 }, { IRCD_CAPAB_VALUE_KLINE, "KLN", 0 }, { IRCD_CAPAB_VALUE_UNKLINE, "UNKLN", 0 }, { IRCD_CAPAB_VALUE_ENCAP, "ENCAP", 0 }, + { IRCD_CAPAB_VALUE_IMODE, "IE", 0 }, { 0, NULL, 0 } }; @@ -1145,6 +1151,8 @@ IRCD_CLIENTLIST *anop = NULL; IRCD_CLIENTLIST *skip = NULL; IRCD_BAN *bans; + IRCD_INVEX *invexs; + IRCD_EXCEPT *excepts; int n = 0; int paralen; int namlen; @@ -1255,6 +1263,79 @@ count = 1; } } + + /* send invex */ + + for(invexs=chptr->invexs;invexs;invexs=invexs->next) + { + if (paralen + (namlen = strlen(invexs->invexstring)) + 10 < 200) + { + *(parabuf+paralen) = ' '; + strcpy(parabuf+paralen+1, invexs->invexstring); + paralen += namlen + 1; + count++; + *cp++ = 'I'; + } + else if (*parabuf) + send = 1; + if (count == 4) + send = 1; + if (send) + { + *cp = '\0'; + send_prefix_to_client(meptr, cptr, "MODE %s %s %s", + chptr->name, modebuf, parabuf); + send = 0; + *parabuf = '\0'; + paralen = 0; + cp = modebuf; + *cp++ = '+'; + if (count != 4) + { + strcpy(parabuf, invexs->invexstring); + paralen = namlen; + *cp++ = 'I'; + } + count = 1; + } + } + + /* send except */ + + for(excepts=chptr->excepts;excepts;excepts=excepts->next) + { + if (paralen + (namlen = strlen(excepts->exceptstring)) + 10 < 200) + { + *(parabuf+paralen) = ' '; + strcpy(parabuf+paralen+1, excepts->exceptstring); + paralen += namlen + 1; + count++; + *cp++ = 'e'; + } + else if (*parabuf) + send = 1; + if (count == 4) + send = 1; + if (send) + { + *cp = '\0'; + send_prefix_to_client(meptr, cptr, "MODE %s %s %s", + chptr->name, modebuf, parabuf); + send = 0; + *parabuf = '\0'; + paralen = 0; + cp = modebuf; + *cp++ = '+'; + if (count != 4) + { + strcpy(parabuf, excepts->exceptstring); + paralen = namlen; + *cp++ = 'e'; + } + count = 1; + } + } + if (*parabuf) { *cp = '\0'; @@ -1673,6 +1754,104 @@ return 1; } +static int _channel_invex_add(IRCD_CHANNEL *chptr, IRCD_CLIENT *pptr, char *str, char *hostptr, ircd_uint32_t net, ircd_uint32_t mask) +{ + IRCD_INVEX *invex; + + if (MyClient(pptr)) + { + collapse(str); + if (chptr->nbans >= (int)vars_value_get_bynum(IRCD_VAR_MAX_BANS)) + return 0; + hostptr = strchr(str, '@'); + assert(hostptr != NULL); + hostptr++; + } + for(invex=chptr->invexs;invex;invex=invex->next) + { + if (MyClient(pptr) && + (!match(invex->invexstring, str) || !match(str, invex->invexstring))) + return 0; + else if (!mycmp(invex->invexstring, str)) + return 0; + } + + invex = (IRCD_invex *)MyMalloc(sizeof(IRCD_invex)); + invex->invexstring = MyStrdup(str); + if (invex->net != -1) + { + invex->net = net; + invex->mask = mask; + invex->firstpart = (char *)MyMalloc(hostptr - str + 1); + memcpy(invex->firstpart, str, hostptr - str); + invex->firstpart[hostptr - str] = '\0'; + } + invex->invextime = Now; + if (IsServer(pptr)) + invex->who = MyStrdup(pptr->name); + else + { + invex->who = MyMalloc(strlen(pptr->name)+strlen(pptr->username)+ + strlen(pptr->hostname)+3); + sprintf(invex->who, "%s!%s@%s", pptr->name, pptr->username, + pptr->hostname); + } + add_invex_to_list(&(chptr->invexs), invex); + chptr->nbans++; + + return 1; +} + + +static int _channel_except_add(IRCD_CHANNEL *chptr, IRCD_CLIENT *pptr, char *str, char *hostptr, ircd_uint32_t net, ircd_uint32_t mask) +{ + IRCD_EXCEPT *except; + + if (MyClient(pptr)) + { + collapse(str); + if (chptr->nbans >= (int)vars_value_get_bynum(IRCD_VAR_MAX_BANS)) + return 0; + hostptr = strchr(str, '@'); + assert(hostptr != NULL); + hostptr++; + } + for(except=chptr->excepts;except;except=except->next) + { + if (MyClient(pptr) && + (!match(except->exceptstring, str) || !match(str, except->exceptstring))) + return 0; + else if (!mycmp(except->exceptstring, str)) + return 0; + } + + except = (IRCD_except *)MyMalloc(sizeof(IRCD_except)); + except->exceptstring = MyStrdup(str); + if (except->net != -1) + { + except->net = net; + except->mask = mask; + except->firstpart = (char *)MyMalloc(hostptr - str + 1); + memcpy(except->firstpart, str, hostptr - str); + except->firstpart[hostptr - str] = '\0'; + } + except->excepttime = Now; + if (IsServer(pptr)) + except->who = MyStrdup(pptr->name); + else + { + except->who = MyMalloc(strlen(pptr->name)+strlen(pptr->username)+ + strlen(pptr->hostname)+3); + sprintf(except->who, "%s!%s@%s", pptr->name, pptr->username, + pptr->hostname); + } + add_except_to_list(&(chptr->excepts), except); + chptr->nbans++; + + return 1; +} + + static int _channel_ban_del(IRCD_CHANNEL *chptr, char *str) { IRCD_BAN *ban; @@ -1695,6 +1874,50 @@ return 1; } +static int _channel_invex_del(IRCD_CHANNEL *chptr, char *str) +{ + IRCD_INVEX *invex; + IRCD_INVEX *nextinvex; + + for(invex=chptr->invexs;invex;invex=nextinvex) + { + nextinvex = invex->next; + if (!str || !mycmp(str, invex->invexstring)) + { + MyFree(invex->invexstring); + if (ban->firstpart) + MyFree(invex->firstpart); + MyFree(invex->who); + del_invex_from_list(&(chptr->invexs), invex); + MyFree(invex); + chptr->nbans--; + } + } + return 1; +} + +static int _channel_except_del(IRCD_CHANNEL *chptr, char *str) +{ + IRCD_EXCEPT *except; + IRCD_EXCEPT *nextexcept; + + for(except=chptr->excepts;except;except=nextexcept) + { + nextexcept = except->next; + if (!str || !mycmp(str, except->exceptstring)) + { + MyFree(except->exceåtstring); + if (except->firstpart) + MyFree(except->firstpart); + MyFree(except->who); + del_except_from_list(&(chptr->excepts), except); + MyFree(except); + chptr->nbans--; + } + } + return 1; +} + static void _channel_invite_add(IRCD_CHANNEL *chptr, IRCD_CLIENT *cptr) { IRCD_INVITE *invite; @@ -1720,9 +1943,25 @@ static int _channel_canjoin(IRCD_CLIENT *pptr, IRCD_CHANNEL *chptr, char *key) { IRCD_INVITE *i = NULL; + int isinvex = NULL; + int isexcept = NULL; + char banstr1[NICKLEN+USERLEN+HOSTLEN+6]; + char banstr2[NICKLEN+USERLEN+HOSTLEN+6]; + char banstr3[NICKLEN+USERLEN+HOSTLEN+6]; + char *hostptr; assert(IsLocal(pptr)); + _make_nick_user_host(pptr->name, pptr->username, pptr->hostname, banstr1, &hostptr); + strcpy(banstr2, banstr1); + strcpy(banstr3, banstr1); + *hostptr = '\0'; + strcpy(banstr2+(hostptr-banstr1), pptr->c_ipstring); + + /* banstr1 just has nick + user@ */ + /* banstr2 has n!u@IP */ + /* banstr3 has n!u@HOST */ + if (chptr->limit && (chptr->numusers >= chptr->limit)) return ERR_CHANNELISFULL; if (chptr->key && (!key || mycmp(chptr->key, key))) @@ -1732,29 +1971,60 @@ for(i=pptr->c_invites_list;i;i=i->next) if (!strcasecmp(i->channel, chptr->name)) break; - if (!i) + if (chptr->invexs) + { + IRCD_INVEX *invex = chptr->invex; + for(;invex;invex=invex->next) + { + if (invex->firstpart) + { + if (!cidr_match(invex->net, invex->mask, pptr->c_rem_ipaddr) && !match(invex->firstpart, banstr1)) + { + isinvex = 1; + break; + } + } + if (!match(ban->banstring, banstr2) || !match(ban->banstring, banstr3)) + { + isinvex = 1; + break; + } + } + + } + if ((!i) && (!isinvex)) return ERR_INVITEONLYCHAN; } + +/* not fixed yet - is except from bans + * what to check first? is excepted or isbanned? + * prolly is except -- arnvid / ievil + */ if (chptr->bans) { + if (chptr->excepts) + { + IRCD_EXCEPT *except = chptr->excepts; + for(;except;except=except->next) + { + if (except->firstpart) + { + if (!cidr_match(except->net, except->mask, pptr->c_rem_ipaddr) && !match(except->firstpart, banstr1)) + { + isexcept = 1; + break; + } + } + if (!match(except->exceptstring, banstr2) || !match(except->exceptstring, banstr3)) + { + isexcept = 1; + break; + } + } + } + if (!isexcept) + { IRCD_BAN *ban = chptr->bans; - char banstr1[NICKLEN+USERLEN+HOSTLEN+6]; - char banstr2[NICKLEN+USERLEN+HOSTLEN+6]; - char banstr3[NICKLEN+USERLEN+HOSTLEN+6]; - char *hostptr; - - _make_nick_user_host(pptr->name, pptr->username, pptr->hostname, - banstr1, &hostptr); - strcpy(banstr2, banstr1); - strcpy(banstr3, banstr1); - - *hostptr = '\0'; - strcpy(banstr2+(hostptr-banstr1), pptr->c_ipstring); - - /* banstr1 just has nick + user@ */ - /* banstr2 has n!u@IP */ - /* banstr3 has n!u@HOST */ - for(;ban;ban=ban->next) { if (ban->firstpart) @@ -1768,6 +2038,7 @@ return ERR_BANNEDFROMCHAN; } } + } if (i) { del_invite_from_list(&(pptr->c_invites_list), i); @@ -3661,6 +3932,7 @@ send_prefix_to_client(meptr, pptr, IRCD_REPLY(RPL_INFO, pptr->name), "Thomas Helvey"); send_prefix_to_client(meptr, pptr, IRCD_REPLY(RPL_INFO, pptr->name), "Fred Jacobs"); send_prefix_to_client(meptr, pptr, IRCD_REPLY(RPL_INFO, pptr->name), "Richard Steenbergen"); + send_prefix_to_client(meptr, pptr, IRCD_REPLY(RPL_INFO, pptr->name), "Arnvid L. Karstad"); send_prefix_to_client(meptr, pptr, IRCD_REPLY(RPL_INFO, pptr->name), "...and I'm sure others that I've forgotten."); send_prefix_to_client(meptr, pptr, IRCD_REPLY(RPL_INFO, pptr->name), ""); sprintf(numbuf, "Current TS Version: %d", TS_CURRENT); @@ -5907,6 +6179,11 @@ IRCD_MODE *lastopmode = NULL; IRCD_MODE *banmodes = NULL; IRCD_MODE *lastbanmode = NULL; + IRCD_MODE *invexmodes = NULL; + IRCD_MODE *lastinvexmode = NULL; + IRCD_MODE *exceptmodes = NULL; + IRCD_MODE *lastexceptmode = NULL; + IRCD_MODE *opmodeptr; char parabuf[512]; char modebuf[512]; @@ -5929,6 +6206,8 @@ int isdeop; int got_ovk = 0; IRCD_BAN *ban; + IRCD_EXCEPT *except; + IRCD_INVEX *invex; int maxmodeparams; if (!IsServer(lptr) && !IsReg(pptr)) @@ -6166,6 +6445,87 @@ opmodeptr->plusminus = plusminus; opmodeptr->banstring = target; break; + case 'I': + target = ircd_next_subarg_space(&modeargs); + if (!target || !*target) + { + /* return invexlist */ + for(invex=chptr->invexs;invex;invex=invex->next) + { + send_prefix_to_client(meptr, pptr, + IRCD_REPLY(RPL_INVEXLIST, pptr->name), + chptr->name, + invex->invexstring, + invex->who, + invex->invextime); + } + send_prefix_to_client(meptr, pptr, + IRCD_REPLY(RPL_ENDOFINVEXLIST, pptr->name), + chptr->name); + break; + } + if (!IsServer(pptr) && !chlptr) + { + send_prefix_to_client(meptr, pptr, + IRCD_REPLY(ERR_NOTONCHANNEL, pptr->name), + chptr->name); + break; + } + if (!ischop) + { + send_prefix_to_client(meptr, pptr, + IRCD_REPLY(ERR_CHANOPRIVSNEEDED, pptr->name), + chptr->name); + break; + } + if (IsClient(lptr) && opcnt++ >= maxmodeparams) + break; + opmodeptr = _ircdmode_create(&invexmodes, &lastinvexmode); + opmodeptr->mode = *ptr; + opmodeptr->plusminus = plusminus; + opmodeptr->invexstring = target; + break; + case 'e': + target = ircd_next_subarg_space(&modeargs); + if (!target || !*target) + { + /* return exceptlist */ + for(except=chptr->excepts;except;except=except->next) + { + send_prefix_to_client(meptr, pptr, + IRCD_REPLY(RPL_EXCEPTLIST, pptr->name), + chptr->name, + except->exceptstring, + except->who, + except->excepttime); + } + send_prefix_to_client(meptr, pptr, + IRCD_REPLY(RPL_ENDOFEXCEPTLIST, pptr->name), + chptr->name); + break; + } + if (!IsServer(pptr) && !chlptr) + { + send_prefix_to_client(meptr, pptr, + IRCD_REPLY(ERR_NOTONCHANNEL, pptr->name), + chptr->name); + break; + } + if (!ischop) + { + send_prefix_to_client(meptr, pptr, + IRCD_REPLY(ERR_CHANOPRIVSNEEDED, pptr->name), + chptr->name); + break; + } + if (IsClient(lptr) && opcnt++ >= maxmodeparams) + break; + opmodeptr = _ircdmode_create(&exceptmodes, &lastexceptmode); + opmodeptr->mode = *ptr; + opmodeptr->plusminus = plusminus; + opmodeptr->exceptstring = target; + break; + case 'l': tlimit = 0; if (plusminus == '+') @@ -6240,6 +6600,7 @@ /* if it's a non-deopped non-op on a TS channel from a TS ** server, allow only ops and deops and ignore everything ** else (to avoid having desynched ops) -orabidoo + ** - could it be this code fucking with services.int? */ if (!ischop && isok) { @@ -6247,6 +6608,8 @@ limitchange = 0; keychange = 0; _ircdmode_free(&banmodes); + _ircdmode_free(&invexmodes); + _ircdmode_free(&exceptmodes); } plusminus = '\0'; @@ -6437,6 +6800,91 @@ } _ircdmode_free(&banmodes); + /* invex */ + for(opmodeptr=invexmodes;opmodeptr;opmodeptr=opmodeptr->next) + { + char *user, *host; + int ret; + ircd_uint32_t net; + ircd_uint32_t mask; + char *hostptr; + + if ((user = strchr(opmodeptr->invexstring, '!')) != NULL) + *user++ = '\0'; + if ((host = strrchr(user?user:opmodeptr->invexstring, '@')) != NULL) + *host++ = '\0'; + sptr = _make_nick_user_host(opmodeptr->invexstring, + user, host, newban, &hostptr); + ret = cidr_ip2netmask(hostptr, &net, &mask); + if (!ret) + net = -1; + + if ((modeargptr-modeargbuf) + + strlen(sptr) + 2 >= sizeof(modeargbuf)) + break; + + if (((opmodeptr->plusminus == '+') && + !_channel_invex_add(chptr, pptr, sptr, hostptr, net, mask)) || + ((opmodeptr->plusminus == '-') && + !_channel_invex_del(chptr, sptr))) + continue; + + if (plusminus != opmodeptr->plusminus) + { + plusminus = opmodeptr->plusminus; + *modeptr++ = plusminus; + } + *modeptr++ = opmodeptr->mode; + if (modeargptr != modeargbuf) + *modeargptr++ = ' '; + for(;*sptr;) + *modeargptr++ = *sptr++; + } + _ircdmode_free(&invexmodes); + + /* except */ + for(opmodeptr=exceptmodes;opmodeptr;opmodeptr=opmodeptr->next) + { + char *user, *host; + int ret; + ircd_uint32_t net; + ircd_uint32_t mask; + char *hostptr; + + if ((user = strchr(opmodeptr->exceptstring, '!')) != NULL) + *user++ = '\0'; + if ((host = strrchr(user?user:opmodeptr->exceptstring, '@')) != NULL) + *host++ = '\0'; + sptr = _make_nick_user_host(opmodeptr->exceptstring, + user, host, newban, &hostptr); + ret = cidr_ip2netmask(hostptr, &net, &mask); + if (!ret) + net = -1; + + if ((modeargptr-modeargbuf) + + strlen(sptr) + 2 >= sizeof(modeargbuf)) + break; + + if (((opmodeptr->plusminus == '+') && + !_channel_except_add(chptr, pptr, sptr, hostptr, net, mask)) || + ((opmodeptr->plusminus == '-') && + !_channel_except_del(chptr, sptr))) + continue; + + if (plusminus != opmodeptr->plusminus) + { + plusminus = opmodeptr->plusminus; + *modeptr++ = plusminus; + } + *modeptr++ = opmodeptr->mode; + if (modeargptr != modeargbuf) + *modeargptr++ = ' '; + for(;*sptr;) + *modeargptr++ = *sptr++; + } + _ircdmode_free(&exceptmodes); + + *modeptr = '\0'; *modeargptr = '\0'; diff -bBuNrd csircd-1.14.vanilla/lib/hash.c csircd-1.14/lib/hash.c --- csircd-1.14.vanilla/lib/hash.c 2003-02-03 03:03:36.000000000 +0100 +++ csircd-1.14/lib/hash.c 2003-09-11 04:18:02.000000000 +0200 @@ -516,6 +516,44 @@ ban->next->prev = ban->prev; } +void add_invex_to_list(IRCD_INVEX **bucket, IRCD_INVEX *invex) +{ + invex->prev = NULL; + if ((invex->next = *bucket) != NULL) + invex->next->prev = invex; + *bucket = invex; +} + +void del_invex_from_list(IRCD_INVEX **bucket, IRCD_INVEX *invex) +{ + if (invex->prev) + invex->prev->next = invex->next; + else + *bucket = invex->next; + if (invex->next) + invex->next->prev = invex->prev; +} + +void add_except_to_list(IRCD_EXCEPT **bucket, IRCD_EXCEPT *except) +{ + except->prev = NULL; + if ((except->next = *bucket) != NULL) + except->next->prev = except; + *bucket = except; +} + +void del_except_from_list(IRCD_EXCEPT **bucket, IRCD_EXCEPT *except) +{ + if (except->prev) + except->prev->next = except->next; + else + *bucket = except->next; + if (except->next) + except->next->prev = except->prev; +} + + + static void add_channel_to_list(IRCD_CHANNEL **bucket, IRCD_CHANNEL *channel) { channel->prev = NULL; diff -bBuNrd csircd-1.14.vanilla/lib/numeric.c csircd-1.14/lib/numeric.c --- csircd-1.14.vanilla/lib/numeric.c 2003-02-04 10:28:29.000000000 +0100 +++ csircd-1.14/lib/numeric.c 2003-09-11 04:08:08.000000000 +0200 @@ -201,10 +201,10 @@ /* 343 */ { 0, (char *)NULL }, /* 344 */ { 0, (char *)NULL }, /* 345 */ { 0, (char *)NULL }, -/* 346 */ { 0, (char *)NULL }, -/* 347 */ { 0, (char *)NULL }, -/* 348 */ { 0, (char *)NULL }, -/* 349 */ { 0, (char *)NULL }, +/* 346 */ { RPL_INVEXLIST, "%s %s %s %u" }, +/* 347 */ { RPL_ENDOFINVEXLIST, "%s :End of Channel Invex List"}, +/* 348 */ { RPL_EXCEPTLIST, "%s %s %s %u" }, +/* 349 */ { RPL_ENDOFEXCEPTLIST, "%s :End of Channel Except List"}, /* 350 */ { 0, (char *)NULL }, /* 351 */ { RPL_VERSION, "%s.%s %s :%s" }, /* 352 */ { RPL_WHOREPLY, "%s %s %s %s %s %s :%d %s" },