diff -ruN -x configure -x *~ -x ircd-hybrid-6.0.orig -x *.rej ircd-hybrid-6.0.orig/include/channel.h ircd-hybrid-6.0/include/channel.h
--- ircd-hybrid-6.0.orig/include/channel.h	Thu May 31 18:02:52 2001
+++ ircd-hybrid-6.0/include/channel.h	Thu May 31 17:40:03 2001
@@ -148,6 +148,7 @@
 #define CHFL_EXCEPTION  0x00000010 /* exception to ban channel flag */
 #define CHFL_DENY       0x00000020 /* regular expression deny flag */
 #define CHFL_INVEX      0x00000040 /* invex channel flag */
+#define CHFL_QUIET      0x00000080 /* quieted on channel -- asuffield */
 
 /* Channel Visibility macros */
 
@@ -170,6 +171,7 @@
 #define MODE_FORWARD    0x00008000  /* -goober */
 #endif
 #define MODE_NOCOLOR    0x00010000  /* AGB */
+#define MODE_QUIET      0x00020000
 #define MODE_FLAGS      0x00004fff  /* was 0x1fff */
 
 #ifdef NEED_SPLITCODE
@@ -240,7 +242,7 @@
 
   - Dianora
 */
-typedef struct Ban      /* also used for exceptions -orabidoo */
+typedef struct Ban      /* also used for exceptions -orabidoo */ /* and for "quieting" -- asuffield */
 {
   char *banstr;
   char *who;
@@ -248,6 +250,7 @@
 #ifdef BAN_CHANNEL_FORWARDING
   struct Channel *ban_forward_chptr;
 #endif
+  char can_join; /* if non-zero, then this is a "quiet" ban and joining the channel is allowed */
 } aBan;
 #endif
 
diff -ruN -x configure -x *~ -x ircd-hybrid-6.0.orig -x *.rej ircd-hybrid-6.0.orig/include/config.h ircd-hybrid-6.0/include/config.h
--- ircd-hybrid-6.0.orig/include/config.h	Thu May 31 18:02:52 2001
+++ ircd-hybrid-6.0/include/config.h	Thu May 31 18:01:56 2001
@@ -811,6 +811,11 @@
  */
 #define NOCOLOUR_MODE
    
+/*
+ * Allow +q channel mode (quiets) as a lightweight ban
+ */
+#define QUIET_MODE
+
 /*   STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP STOP  */
 
 /* You shouldn't change anything below this line, unless absolutely needed. */
diff -ruN -x configure -x *~ -x ircd-hybrid-6.0.orig -x *.rej ircd-hybrid-6.0.orig/include/s_serv.h ircd-hybrid-6.0/include/s_serv.h
--- ircd-hybrid-6.0.orig/include/s_serv.h	Thu May 31 18:02:51 2001
+++ ircd-hybrid-6.0/include/s_serv.h	Thu May 31 17:40:03 2001
@@ -46,6 +46,7 @@
 #define CAP_CHW         0x00000010      /* Can do channel wall @# */
 #define CAP_DE          0x00000020      /* Can do channel +d (regex deny) */
 #define CAP_IE          0x00000040      /* can do +I */
+#define CAP_QU          0x00000080      /* can do +q (quiet) */
 #define CAP_OPN         0x10000000      /* Can do sethost, setident, setname,
                                            allows opers to hack modes, accepts
                                            glines without vote, has nicklen 30
diff -ruN -x configure -x *~ -x ircd-hybrid-6.0.orig -x *.rej ircd-hybrid-6.0.orig/src/channel.c ircd-hybrid-6.0/src/channel.c
--- ircd-hybrid-6.0.orig/src/channel.c	Thu May 31 18:02:52 2001
+++ ircd-hybrid-6.0/src/channel.c	Thu May 31 17:59:51 2001
@@ -108,6 +108,7 @@
 static  char    buf[BUFSIZE];
 static  char    modebuf[MODEBUFLEN], modebuf2[MODEBUFLEN];
 static  char    parabuf[MODEBUFLEN], parabuf2[MODEBUFLEN];
+static  char    maskbuf[256]; /* used in set_channel_mode() when constructing banlist (better ideas?) -- asuffield */
 
 
 /* 
@@ -184,6 +185,9 @@
 {
   struct SLink  *ban;
   struct SLink  **list;
+#ifdef QUIET_MODE
+  char can_join = 0;
+#endif
 
   /* dont let local clients overflow the banlist */
   if ((!IsServer(cptr)) && (chptr->num_bed >= MAXBANS))
@@ -202,6 +206,13 @@
     {
     case CHFL_BAN:
       list = &chptr->banlist;
+#ifdef QUIET_MODE
+      can_join = 0;
+      break;
+    case CHFL_QUIET:
+      list = &chptr->banlist;
+      can_join = 1;
+#endif
       break;
     case CHFL_EXCEPTION:
       list = &chptr->exceptlist;
@@ -229,6 +240,9 @@
   ban->value.banptr = (aBan *)MyMalloc(sizeof(aBan));
   ban->value.banptr->banstr = (char *)MyMalloc(strlen(banid)+1);
   (void)strcpy(ban->value.banptr->banstr, banid);
+#ifdef QUIET_MODE
+  ban->value.banptr->can_join = can_join;
+#endif
 
   if (IsPerson(cptr))
     {
@@ -277,6 +291,7 @@
   switch(type)
     {
     case CHFL_BAN:
+    case CHFL_QUIET:
       list = &chptr->banlist;
       break;
     case CHFL_EXCEPTION:
@@ -397,8 +412,9 @@
 
 /*
  * is_banned -  returns an int 0 if not banned,
- *              CHFL_BAN if banned (or +d'd)
+ *              CHFL_BAN if banned (or +d'd) (only if cannot join -- asuffield)
  *              CHFL_EXCEPTION if they have a ban exception
+ *              CHFL_QUIET if cannot send to channel  -- asuffield
  *
  * IP_BAN_ALL from comstud
  * always on...
@@ -421,9 +437,20 @@
                            inetntoa((char*) &cptr->ip));
 
   for (tmp = chptr->banlist; tmp; tmp = tmp->next)
+#ifdef QUIET_MODE
+    if (match(BANSTR(tmp), s) ||
+	match(BANSTR(tmp), s2))
+      {
+        if (tmp->value.banptr->can_join) /* really banned? or just quieted? */
+	  return CHFL_QUIET;
+        else
+	  break;
+      }
+#else
     if (match(BANSTR(tmp), s) ||
         match(BANSTR(tmp), s2))
       break;
+#endif
 
   if (!tmp) {  /* check +d list */
     for (tmp = chptr->denylist; tmp; tmp = tmp->next)
@@ -445,7 +470,13 @@
 
   /* return CHFL_BAN for +b or +d match, we really dont need to be more
      specific */
+  /* return CHFL_QUIET as well, since you can't send to channel when 
+     banned -- asuffield */
+#ifdef QUIET_MODE
+  return ((tmp?(CHFL_BAN | CHFL_QUIET):0));
+#else
   return ((tmp?CHFL_BAN:0));
+#endif
 }
 
 static  int is_invex(struct Client *cptr,struct Channel *chptr)
@@ -628,7 +659,11 @@
   if (chptr->mode.mode & MODE_NOPRIVMSGS && !lp)
     return (MODE_NOPRIVMSGS);
 
+#ifdef QUIET_MODE
+  if ((is_banned(cptr, chptr) & CHFL_QUIET) &&
+#else
   if (is_banned(cptr, chptr) == CHFL_BAN &&
+#endif
       (!lp || !(lp->flags & (CHFL_CHANOP|CHFL_VOICE))))
     return (MODE_MODERATED);
 
@@ -722,6 +757,12 @@
     {
       if (!(lp->flags & mask))
         continue;
+#ifdef QUIET_MODE
+      if ((mask & CHFL_BAN) && lp->value.banptr->can_join)
+	continue;
+      if ((mask & CHFL_QUIET) && !lp->value.banptr->can_join)
+	continue;
+#endif
       name = BANSTR(lp);
 #ifdef BAN_CHANNEL_FORWARDING     
       if ((mask & CHFL_BAN) && (lp->value.banptr->ban_forward_chptr))
@@ -901,6 +942,19 @@
 	sendto_one(cptr, ":%s MODE %s %s %s",
 		   me.name, chptr->chname, modebuf, parabuf);
     }
+#ifdef QUIET_MODE
+  if (IsCapable(cptr, CAP_QU))
+    {
+      *parabuf = '\0';
+      *modebuf = '+';
+      modebuf[1] = '\0';
+      send_mode_list(cptr, chptr->chname, chptr->banlist, CHFL_QUIET,'q');
+
+      if (modebuf[1] || *parabuf)
+	sendto_one(cptr, ":%s MODE %s %s %s",
+		   me.name, chptr->chname, modebuf, parabuf);
+    }
+#endif
 }
 
 /* stolen from Undernet's ircd  -orabidoo
@@ -1052,6 +1106,7 @@
    */
   char  *mbufw = modebuf, *mbuf2w = modebuf2;
   char  *pbufw = parabuf, *pbuf2w = parabuf2;
+  char  *maskbufw = maskbuf;
 
   int   ischop;
   int   isok;
@@ -1655,6 +1710,9 @@
 
           break;
 
+#ifdef QUIET_MODE
+	case 'q':
+#endif
         case 'b':
           if (whatt == MODE_QUERY || parc-- <= 0)
             {
@@ -1669,30 +1727,81 @@
 #endif
 		{
 		  for (lp = chptr->banlist; lp; lp = lp->next)
-		    sendto_one(cptr, form_str(RPL_BANLIST),
-			       me.name, cptr->name,
-			       chptr->chname,
-			       lp->value.banptr->banstr,
-			       lp->value.banptr->who,
-			       lp->value.banptr->when);
+#ifdef QUIET_MODE
+		    {
+		      if (lp->value.banptr->can_join)
+			{
+			  maskbufw = maskbuf;
+			  ircsprintf(maskbufw,"%%%s",lp->value.banptr->banstr);
+			}
+		      else
+			maskbufw = lp->value.banptr->banstr;
+		      sendto_one(cptr, form_str(RPL_BANLIST),
+				 me.name, cptr->name,
+				 chptr->chname,
+				 maskbufw,
+				 lp->value.banptr->who,
+				 lp->value.banptr->when);
+		    }
+#else /* QUIET_MODE */
+ 		    sendto_one(cptr, form_str(RPL_BANLIST),
+ 			       me.name, cptr->name,
+ 			       chptr->chname,
+ 			       lp->value.banptr->banstr,
+ 			       lp->value.banptr->who,
+ 			       lp->value.banptr->when);
+#endif /* QUIET_MODE */
 		}
 #ifdef HIDE_OPS
 	      else
 		{
 		  for (lp = chptr->banlist; lp; lp = lp->next)
-		    sendto_one(cptr, form_str(RPL_BANLIST),
-			       me.name, cptr->name,
-			       chptr->chname,
-			       lp->value.banptr->banstr,
-			       "*",0);
+#ifdef QUIET_MODE
+		    {
+		      if (lp->value.banptr->can_join)
+			{
+			  maskbufw = maskbuf;
+			  ircsprintf(maskbufw,"%%%s",lp->value.banptr->banstr);
+			}
+		      else
+			maskbufw = lp->value.banptr->banstr;
+		      sendto_one(cptr, form_str(RPL_BANLIST),
+				 me.name, cptr->name,
+				 chptr->chname,
+				 maskbufw,
+				 "*",0);
+		    }
+#else /* QUIET_MODE */
+ 		    sendto_one(cptr, form_str(RPL_BANLIST),
+ 			       me.name, cptr->name,
+ 			       chptr->chname,
+ 			       lp->value.banptr->banstr,
+ 			       "*",0);
+#endif /* QUIET_MODE */
 		}
-#endif
+#endif /* HIDE_OPS */
 #else 
               for (lp = chptr->banlist; lp; lp = lp->next)
+#ifdef QUIET_MODE
+		{
+		  if (lp->value.banptr->can_join)
+		    {
+		      maskbufw = maskbuf;
+		      ircsprintf(maskbufw,"%%%s",lp->value.banptr->banstr);
+		    }
+		  else
+		    maskbufw = lp->value.banptr->banstr;
+		  sendto_one(cptr, form_str(RPL_BANLIST),
+			     me.name, cptr->name,
+			     chptr->chname,
+			     maskbufw);
+		}
+#else /* QUIET_MODE */
                 sendto_one(cptr, form_str(RPL_BANLIST),
                            me.name, cptr->name,
                            chptr->chname,
                            lp->value.cp);
+#endif /* QUIET_MODE */
 #endif
               sendto_one(sptr, form_str(RPL_ENDOFBANLIST),
                          me.name, sptr->name, 
@@ -1710,6 +1819,18 @@
             }
 
           arg = check_string(*parv++);
+#ifdef QUIET_MODE
+	  if (whatt == MODE_DEL)
+	    {
+	      /* If we're removing a ban, and there is a leading %, odds are that
+	       * the client is just deleting something it saw in the ban list.
+	       * Silently remove it, as that's the indicator for a quiet ban
+	       * -- asuffield
+	       */
+	      if (*arg == '%')
+		arg++;
+	    }
+#endif
 
           if (MyClient(sptr) && opcnt >= MAXMODEPARAMS)
             break;
@@ -1779,9 +1900,23 @@
           if (len + tmp + 2 >= MODEBUFLEN)
             break;
 
+#ifdef QUIET_MODE
+	  {
+	    int type = 0;
+	    if (c == 'b')
+	      type = CHFL_BAN;
+	    else if (c == 'q')
+	      type = CHFL_QUIET;
+	    
+	    if (!(((whatt & MODE_ADD) && !add_id(sptr, chptr, arg, type)) ||
+		  ((whatt & MODE_DEL) && !del_id(chptr, arg, type))))
+	      break;
+	  }
+#else /* QUIET_MODE */
           if (!(((whatt & MODE_ADD) && !add_id(sptr, chptr, arg, CHFL_BAN)) ||
                 ((whatt & MODE_DEL) && !del_id(chptr, arg, CHFL_BAN))))
             break;
+#endif /* QUIET_MODE */
 
 #ifdef BAN_CHANNEL_FORWARDING
 	  if ((whatt & MODE_ADD) && fchname)
@@ -1793,7 +1928,7 @@
 #endif
 
           *mbufw++ = plus;
-          *mbufw++ = 'b';
+          *mbufw++ = c;
 	  strcpy(pbufw, arg);
 #ifdef BAN_CHANNEL_FORWARDING
 	  if ((whatt & MODE_ADD) && fchname)
@@ -2388,7 +2523,15 @@
     }
 #endif
 
+#ifdef QUIET_MODE
+  /* watch this if is_banned() changes, at present there is no way that
+     CHFL_QUIET can be returned unless CHFL_BAN is also returned,
+     but this may need rewriting if that ceases to be the case
+     -- asuffield */
+  if ( (ban_or_exception = is_banned(sptr, chptr)) & CHFL_BAN)
+#else
   if ( (ban_or_exception = is_banned(sptr, chptr)) == CHFL_BAN)
+#endif
     return (ERR_BANNEDFROMCHAN);
   else
     *flags |= ban_or_exception; /* Mark this client as "charmed" */
@@ -3786,8 +3929,13 @@
     }
 
   /* don't allow a knock if the user is banned, or the channel is secret */
+  /*  or if the user is quieted on the channel  -- asuffield */
   if ((chptr->mode.mode & MODE_SECRET) || 
+#ifdef QUIET_MODE
+      (is_banned(sptr, chptr) & (CHFL_BAN | CHFL_QUIET)) )
+#else
       (is_banned(sptr, chptr) == CHFL_BAN) )
+#endif
     {
       sendto_one(sptr, form_str(ERR_CANNOTSENDTOCHAN), me.name, parv[0],
                  name);
diff -ruN -x configure -x *~ -x ircd-hybrid-6.0.orig -x *.rej ircd-hybrid-6.0.orig/src/s_serv.c ircd-hybrid-6.0/src/s_serv.c
--- ircd-hybrid-6.0.orig/src/s_serv.c	Thu May 31 18:02:51 2001
+++ ircd-hybrid-6.0/src/s_serv.c	Thu May 31 17:56:02 2001
@@ -76,6 +76,9 @@
   { "DE",       CAP_DE },
   { "OPN",      CAP_OPN },
   { "IE", 	CAP_IE }, 
+#ifdef QUIET_MODE
+  { "QU",       CAP_QU },
+#endif
   { 0,   0 }
 };
 
