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" },
