--- ircd-hybrid-6.0/include/channel.h.orig	Sat Apr 14 13:19:23 2001
+++ ircd-hybrid-6.0/include/channel.h	Sat Apr 14 15:10:49 2001
@@ -116,7 +116,7 @@
 extern void    channel_modes(struct Client *, char *, char *, struct Channel*);
 extern void    set_channel_mode(struct Client *, struct Client *, 
                                 struct Channel *, int, char **);
-
+extern char*   pretty_mask(char *);
 
 
 /* this should eliminate a lot of ifdef's in the main code... -orabidoo */
--- ircd-hybrid-6.0/include/client.h.orig	Sat Apr 14 13:19:24 2001
+++ ircd-hybrid-6.0/include/client.h	Sat Apr 14 15:10:49 2001
@@ -75,6 +75,7 @@
   struct User*   next;          /* chain of anUser structures */
   struct SLink*  channel;       /* chain of channel pointer blocks */
   struct SLink*  invited;       /* chain of invite pointer blocks */
+  struct SLink*  silence;       /* chain of silence pointer blocks */
   char*          away;          /* pointer to away message */
   time_t         last;
   int            refcnt;        /* Number of times this block is referenced */
--- ircd-hybrid-6.0/include/ircd_defs.h.orig	Sat Apr 14 13:19:21 2001
+++ ircd-hybrid-6.0/include/ircd_defs.h	Sat Apr 14 15:10:49 2001
@@ -50,6 +50,8 @@
 #define MAXRECIPIENTS   20
 #define MAXBANS         25      /* bans + exceptions together */
 #define MAXBANLENGTH    1024
+#define MAXSILES        50
+#define MAXSILELENGTH   128
 
 #define OPERWALL_LEN    400     /* can be truncated on other servers */
 
--- ircd-hybrid-6.0/include/m_commands.h.orig	Sat Apr 14 13:19:23 2001
+++ ircd-hybrid-6.0/include/m_commands.h	Sat Apr 14 15:10:49 2001
@@ -115,4 +115,6 @@
 extern int m_global(struct Client *,struct Client *,int,char **);
 #endif /* USE_SERVICES */
 
+extern int m_silence(struct Client *, struct Client *, int, char**);
+
 #endif /* INCLUDED_m_commands_h */
--- ircd-hybrid-6.0/include/msg.h.orig	Sat Apr 14 13:19:23 2001
+++ ircd-hybrid-6.0/include/msg.h	Sat Apr 14 15:10:49 2001
@@ -117,6 +117,7 @@
 #define MSG_DLINE    "DLINE"    /* DLINE */
 #define MSG_HTM      "HTM"      /* HTM */
 #define MSG_SET      "SET"      /* SET */
+#define MSG_SILENCE  "SILENCE"  /* SILENCE */
 
 #define MSG_GLINE    "GLINE"    /* GLINE */
 
@@ -270,6 +271,7 @@
   { MSG_DIE, m_die,          0, MAXPARA, 1, 0, 0, 0L },
   { MSG_HTM,    m_htm,       0, MAXPARA, 1, 0, 0, 0L },
   { MSG_SET,    m_set,       0, MAXPARA, 1, 0, 0, 0L },
+  { MSG_SILENCE,  m_silence, 0, MAXPARA, 1, 0, 1, 0L },
   { MSG_TESTLINE, m_testline,0, MAXPARA, 1, 0, 0, 0L },
   { MSG_CHANSERV, m_chanserv,      0, 1, 1, 0, 1, 0L },
   { MSG_CS,       m_chanserv,      0, 1, 1, 0, 1, 0L },
--- ircd-hybrid-6.0/include/numeric.h.orig	Sat Apr 14 13:19:22 2001
+++ ircd-hybrid-6.0/include/numeric.h	Sat Apr 14 15:10:49 2001
@@ -205,6 +205,9 @@
 #define RPL_LOCALUSERS       265
 #define RPL_GLOBALUSERS      266
 
+#define RPL_SILELIST         271
+#define RPL_ENDOFSILELIST    272
+
 /* numeric_replies */
 
 #define RPL_NONE             300
@@ -349,5 +352,7 @@
 
 #define ERR_GHOSTEDCLIENT    503
 #define ERR_LAST_ERR_MSG     504
+
+#define ERR_SILELISTFULL     511
 
 #endif /* INCLUDED_numeric_h */
--- ircd-hybrid-6.0/include/s_user.h.orig	Fri Jul 30 19:44:44 1999
+++ ircd-hybrid-6.0/include/s_user.h	Sat Apr 14 15:10:49 2001
@@ -44,6 +44,7 @@
 extern void  send_umode_out (struct Client*, struct Client *, int);
 extern int   show_lusers(struct Client *, struct Client *, int, char **);
 extern void  show_opers(struct Client* client);
-
+extern int   del_silence(struct Client *, char *);
+extern int   is_silenced(struct Client *, struct Client *);
 
 #endif
--- ircd-hybrid-6.0/src/channel.c.orig	Sat Apr 14 13:19:23 2001
+++ ircd-hybrid-6.0/src/channel.c	Sat Apr 14 15:10:49 2001
@@ -84,7 +84,6 @@
 
 
 /* static functions used in set_mode */
-static char* pretty_mask(char *);
 static char *fix_key(char *);
 static char *fix_key_old(char *);
 static void collapse_signs(char *);
@@ -1013,7 +1012,7 @@
  *
  */
 
-static char* pretty_mask(char* mask)
+char* pretty_mask(char* mask)
 {
   register char* cp = mask;
   register char* user;
--- ircd-hybrid-6.0/src/client.c.orig	Sat Apr 14 13:19:22 2001
+++ ircd-hybrid-6.0/src/client.c	Sat Apr 14 15:10:49 2001
@@ -45,6 +45,7 @@
 #include "struct.h"
 #include "whowas.h"
 #include "s_debug.h"
+#include "s_user.h"
 
 #include <assert.h>
 #include <fcntl.h>
@@ -1220,6 +1221,10 @@
           while ((lp = sptr->user->invited))
             del_invite(sptr, lp->value.chptr);
           /* again, this is all that is needed */
+
+          /* Clean up silencefield */
+          while ((lp = sptr->user->silence))
+            del_silence(sptr, lp->value.cp);
         }
     }
   
--- ircd-hybrid-6.0/src/list.c.orig	Sat Nov 18 11:11:11 2000
+++ ircd-hybrid-6.0/src/list.c	Sat Apr 14 15:10:49 2001
@@ -140,6 +140,7 @@
       user->joined = 0;
       user->channel = NULL;
       user->invited = NULL;
+      user->silence = NULL;
       cptr->user = user;
     }
   return user;
--- ircd-hybrid-6.0/src/m_message.c.orig	Sat Apr 14 13:19:24 2001
+++ ircd-hybrid-6.0/src/m_message.c	Sat Apr 14 15:10:49 2001
@@ -35,6 +35,7 @@
 #include "irc_string.h"
 #include "hash.h"
 #include "class.h"
+#include "s_user.h"
 
 #include <string.h>
 
@@ -370,13 +371,16 @@
             }
         }
 #endif
-      if (!notice && MyConnect(sptr) &&
-          acptr->user && acptr->user->away)
-        sendto_one(sptr, form_str(RPL_AWAY), me.name,
-                   parv[0], acptr->name,
-                   acptr->user->away);
-      sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
-                        parv[0], cmd, nick, parv[2]);
+
+      if (!is_silenced(sptr, acptr)) {
+          if (!notice && MyConnect(sptr) &&
+              acptr->user && acptr->user->away)
+            sendto_one(sptr, form_str(RPL_AWAY), me.name,
+                       parv[0], acptr->name,
+                       acptr->user->away);
+          sendto_prefix_one(acptr, sptr, ":%s %s %s :%s",
+                            parv[0], cmd, nick, parv[2]);
+      }
 
 #ifdef  IDLE_CHECK
       /* reset idle time for message only if its not to self */
--- ircd-hybrid-6.0/src/m_whois.c.orig	Sat Apr 14 13:19:23 2001
+++ ircd-hybrid-6.0/src/m_whois.c	Sat Apr 14 15:10:49 2001
@@ -111,6 +111,7 @@
     NULL,       /* next */
     NULL,       /* channel */
     NULL,       /* invited */
+    NULL,       /* silence */
     NULL,       /* away */
     0,          /* last */
     1,          /* refcount */
--- ircd-hybrid-6.0/src/messages.tab.orig	Sat Apr 14 13:19:22 2001
+++ ircd-hybrid-6.0/src/messages.tab	Sat Apr 14 15:10:49 2001
@@ -298,8 +298,8 @@
 /* 268 */       (char *)NULL,
 /* 269 */       (char *)NULL,
 /* 270 */       (char *)NULL,
-/* 271 */       (char *)NULL,
-/* 272 */       (char *)NULL,
+/* 271 RPL_SILELIST, */         ":%s 271 %s %s %s",
+/* 272 RPL_ENDOFSILELIST, */    ":%s 272 %s :End of Silence List",
 /* 273 */       (char *)NULL,
 /* 274 */       (char *)NULL,
 /* 275 */       (char *)NULL,
@@ -547,7 +547,14 @@
 /* 502 ERR_USERSDONTMATCH, */   ":%s 502 %s :Can't change mode for other users",
 /* 503 ERR_GHOSTEDCLIENT, */    ":%s 503 %s :Message could not be delivered to %s",
 /* 504 LAST ERR_LAST_ERR_MSG, */        ":%s 504 %s :Last Error Message",
-                (char *)NULL
+                (char *)NULL,
+/* 505 */       (char *)NULL,
+/* 506 */       (char *)NULL,
+/* 507 */       (char *)NULL,
+/* 508 */       (char *)NULL,
+/* 509 */       (char *)NULL,
+/* 510 */       (char *)NULL,
+/* 511 ERR_SILELISTFULL, */ ":%s 511 %s :Your silence list is full"
 };
 
 
--- ircd-hybrid-6.0/src/messages_cust.tab.orig	Sat Apr 14 13:19:22 2001
+++ ircd-hybrid-6.0/src/messages_cust.tab	Sat Apr 14 15:10:49 2001
@@ -299,8 +299,8 @@
 /* 268 */       (char *)NULL,
 /* 269 */       (char *)NULL,
 /* 270 */       (char *)NULL,
-/* 271 */       (char *)NULL,
-/* 272 */       (char *)NULL,
+/* 271 RPL_SILELIST, */         ":%s 271 %s %s %s",
+/* 272 RPL_ENDOFSILELIST, */    ":%s 272 %s :End of Silence List",
 /* 273 */       (char *)NULL,
 /* 274 */       (char *)NULL,
 /* 275 */       (char *)NULL,
@@ -548,7 +548,14 @@
 /* 502 ERR_USERSDONTMATCH, */   ":%s 502 %s :You can't change someone else's modes",
 /* 503 ERR_GHOSTEDCLIENT, */    ":%s 503 %s :Message could not be delivered to %s",
 /* 504 LAST ERR_LAST_ERR_MSG, */        ":%s 504 %s :Last Error Message",
-                (char *)NULL
+                (char *)NULL,
+/* 505 */       (char *)NULL,
+/* 506 */       (char *)NULL,
+/* 507 */       (char *)NULL,
+/* 508 */       (char *)NULL,
+/* 509 */       (char *)NULL,
+/* 510 */       (char *)NULL,
+/* 511 ERR_SILELISTFULL, */ ":%s 511 %s :Your silence list is full" 
 };
 
 
--- ircd-hybrid-6.0/src/s_user.c.orig	Sat Apr 14 13:19:23 2001
+++ ircd-hybrid-6.0/src/s_user.c	Sat Apr 14 15:12:33 2001
@@ -75,6 +75,7 @@
 static int tell_user_off(aClient *,char **);
 static void send_umode_out_oper (struct Client*, struct Client*, int,
                                  struct Client*);
+int add_silence(struct Client *, char *);
 
 /* table of ascii char letters to corresponding bitmask */
 
@@ -1891,6 +1892,95 @@
 
 
 /*
+ * is_silence : Does the actual check whether sptr is allowed
+ *              to send a message to acptr.
+ *              Both must be registered persons.
+ * If sptr is silenced by acptr, his message should not be propagated,
+ * but moreover, if this is detected on a server not local to sptr
+ * the SILENCE mask is sent upstream.
+ */
+int is_silenced(aClient *sptr, aClient *acptr)
+{
+    Link *lp;
+    anUser *user;
+    static char sender[HOSTLEN + NICKLEN + USERLEN + 5];
+
+    if (!(acptr->user) || !(lp = acptr->user->silence) ||
+        !(user = sptr->user))
+        return 0;
+    ircsprintf(sender, "%s!%s@%s", sptr->name, sptr->username, sptr->host);
+    for (; lp; lp = lp->next) {
+        if (match(lp->value.cp, sender)) {
+            if (!MyConnect(sptr)) {
+                sendto_one(sptr->from, ":%s SILENCE %s :%s", acptr->name,
+                           sptr->name, lp->value.cp);
+                lp->flags = 1;
+            }
+            return 1;
+        }
+    }
+    return 0;
+}
+
+/*
+** m_silence - borrowed from Cyclone
+**      parv[0] = sender prefix
+**      parv[1] = mask (NULL sends the list)
+*/
+int m_silence(aClient* cptr, aClient* sptr, int parc, char *parv[])
+{
+    Link *lp;
+    aClient *acptr;
+    char c = 0, *cp;
+
+    /* if (MyClient(sptr)) { */
+        acptr = sptr;
+        if (parc < 2 || *parv[1] == '\0' || (acptr = find_person(parv[1], NULL))) {
+            if (!(acptr->user))
+                return 0;
+            for (lp = acptr->user->silence; lp; lp = lp->next)
+                sendto_one(sptr, form_str(RPL_SILELIST), me.name,
+                           sptr->name, acptr->name, lp->value.cp);
+            sendto_one(sptr, form_str(RPL_ENDOFSILELIST), me.name, acptr->name);
+            return 0;
+        }
+        cp = parv[1];
+        c = *cp;
+        if (c == '-' || c == '+')
+            cp++;
+        else if (!(index(cp, '@') || index(cp, '.') ||
+                   index(cp, '!') || index(cp, '*'))) {
+            sendto_one(sptr, form_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
+            return -1;
+        } else
+            c = '+';
+        cp = pretty_mask(cp);
+        if ((c == '-' && !del_silence(sptr, cp)) ||
+            (c != '-' && !add_silence(sptr, cp))) {
+            sendto_serv_butone(NULL, ":%s SILENCE %c%s", sptr->name, c, cp);
+        }
+    /* } else if (parc < 3 || *parv[2] == '\0') {
+        sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "SILENCE");
+        return -1;
+    } else if ((c == *parv[2]) == '-' || (acptr = find_person(parv[1], NULL))) {
+        if (c == '-') {
+            if (!del_silence(sptr, parv[2] + 1))
+                sendto_serv_butone(cptr, ":%s SILENCE %s :%s",
+                                   parv[0], parv[1], parv[2]);
+        } else {
+            (void) add_silence(sptr, parv[2]);
+            if (!MyClient(acptr))
+                sendto_one(acptr, ":%s SILENCE %s :%s",
+                           parv[0], parv[1], parv[2]);
+        }
+    } else {
+        sendto_one(sptr, form_str(ERR_NOSUCHNICK), me.name, parv[0], parv[1]);
+        return -1;
+    } */
+    return 0;
+}
+
+/*
 ** do_user
 */
 static int do_user(char* nick, aClient* cptr, aClient* sptr,
@@ -2369,3 +2463,47 @@
 }
 #endif
 
+int del_silence(struct Client *sptr, char *mask)
+{
+    Link **lp, *tmp;
+
+    for (lp = &(sptr->user->silence); *lp; lp = &((*lp)->next))
+        if (strcasecmp(mask, (*lp)->value.cp) == 0) {
+            tmp = *lp;
+            *lp = tmp->next;
+            MyFree(tmp->value.cp);
+            free_link(tmp);
+            return 0;
+        }
+
+    return -1;
+}
+
+int add_silence(struct Client *sptr, char *mask)
+{
+    Link *lp;
+    int cnt = 0, len = 0;
+
+    for (lp = sptr->user->silence; lp; lp = lp->next) {
+        len += strlen(lp->value.cp);
+        if (MyClient(sptr)) {
+            if ((len > MAXSILELENGTH) || (++cnt >= MAXSILES)) {
+                sendto_one(sptr, form_str(ERR_SILELISTFULL), me.name, sptr->name, mask);
+                return -1;
+            } else {
+                if (match(lp->value.cp, mask))
+                    return -1;
+            }
+        } else if (!strcasecmp(lp->value.cp, mask)) {
+            return -1;
+        }
+    }
+
+    lp = make_link();
+    lp->value.cp = (char *) MyMalloc(strlen(mask) + 1);
+    (void) strcpy(lp->value.cp, mask);
+    lp->next = sptr->user->silence;
+    sptr->user->silence = lp;
+
+    return 0;
+}
