diff -ur ircd-ratbox-1.1-2/include/client.h ircd-ratbox-1.1-2+opercheats/include/client.h
--- ircd-ratbox-1.1-2/include/client.h	2003-06-09 21:51:34.000000000 +0100
+++ ircd-ratbox-1.1-2+opercheats/include/client.h	2003-06-13 12:24:23.000000000 +0100
@@ -379,7 +379,7 @@
 #define UMODE_CALLERID     0x2000	/* block unless caller id's */
 #define UMODE_UNAUTH       0x4000	/* show unauth connects here */
 #define UMODE_LOCOPS       0x8000	/* show locops */
-
+#define UMODE_OPERSPY	   0x10000
 /* user information flags, only settable by remote mode or local oper */
 #define UMODE_OPER         0x20000	/* Operator */
 #define UMODE_ADMIN        0x40000	/* Admin on server */
@@ -398,7 +398,7 @@
 #define OPER_REHASH             0x000080
 #define OPER_ADMIN              0x000100
 #define OPER_XLINE              0x000200
-/*      OPER_SPY                0x000400 */
+#define OPER_SPY                0x000400
 /*				0x000800 */
 #define OPER_RESV		0x001000 /* XXX - only here for shared {}; */
 #define OPER_OPERWALL		0x002000
@@ -406,7 +406,7 @@
 #define OPER_FLAGS      (OPER_GLOBAL_KILL | OPER_REMOTE | OPER_UNKLINE |\
                          OPER_GLINE | OPER_N | OPER_K | OPER_DIE |\
                          OPER_REHASH | OPER_ADMIN | OPER_XLINE | OPER_OPERWALL|\
-                         0x000400 | OPER_HIDDENADMIN)
+                         OPER_HIDDENADMIN | OPER_SPY)
 
 #define FLAGS2_EXEMPTGLINE      0x008000
 #define FLAGS2_EXEMPTKLINE      0x010000
@@ -424,7 +424,7 @@
                       UMODE_REJ | UMODE_SKILL | UMODE_FULL | UMODE_SPY | \
                       UMODE_NCHANGE | UMODE_OPERWALL | UMODE_DEBUG | \
                       UMODE_BOTS | UMODE_EXTERNAL | UMODE_LOCOPS | \
- 		      UMODE_ADMIN | UMODE_UNAUTH | UMODE_CALLERID)
+ 		      UMODE_ADMIN | UMODE_UNAUTH | UMODE_CALLERID |UMODE_OPERSPY)
 
 #define FLAGS_ID     (FLAGS_NEEDID | FLAGS_GOTID)
 
@@ -531,6 +531,9 @@
 #define IsOperHiddenAdmin(x)    ((x)->flags2 & OPER_HIDDENADMIN)
 #define IsOperAdmin(x)          (((x)->flags2 & OPER_ADMIN) || \
                                  ((x)->flags2 & OPER_HIDDENADMIN))
+#define IsOperSpy(x)            ((x)->flags2 & OPER_SPY)
+#define SetOperSpy(x)           ((x)->flags2 |= OPER_SPY)
+
 #define IsOperOperwall(x)	((x)->flags2 & OPER_OPERWALL)
 
 #define IsFloodDone(x)          ((x)->flags2 & FLAGS2_FLOODDONE)
diff -ur ircd-ratbox-1.1-2/include/newconf.h ircd-ratbox-1.1-2+opercheats/include/newconf.h
--- ircd-ratbox-1.1-2/include/newconf.h	2003-06-09 21:51:34.000000000 +0100
+++ ircd-ratbox-1.1-2+opercheats/include/newconf.h	2003-06-13 12:24:23.000000000 +0100
@@ -116,6 +116,7 @@
 void conf_set_logging_fname_userlog(void *data);
 void conf_set_logging_fname_foperlog(void *data);
 void conf_set_logging_fname_operlog(void *data);
+void conf_set_logging_fname_operspylog(void *data);
 
 int conf_begin_oper(struct TopConf *tc);
 int conf_end_oper(struct TopConf *tc);
@@ -139,6 +140,7 @@
 void conf_set_oper_admin(void *data);
 void conf_set_oper_hidden_admin(void *data);
 void conf_set_oper_flags(void *data);
+void conf_set_oper_operspy(void *data);
 
 int conf_begin_class(struct TopConf *tc);
 int conf_end_class(struct TopConf *tc);
@@ -245,6 +247,7 @@
 void conf_set_cluster_name(void *data);
 void conf_set_cluster_type(void *data);
 
+void conf_set_general_operspy_admin_only(void *data);
 void conf_set_general_failed_oper_notice(void *data);
 void conf_set_general_anti_nick_flood(void *data);
 void conf_set_general_max_nick_time(void *data);
diff -ur ircd-ratbox-1.1-2/include/s_conf.h ircd-ratbox-1.1-2+opercheats/include/s_conf.h
--- ircd-ratbox-1.1-2/include/s_conf.h	2003-06-13 10:50:50.000000000 +0100
+++ ircd-ratbox-1.1-2+opercheats/include/s_conf.h	2003-06-13 12:24:23.000000000 +0100
@@ -185,6 +185,8 @@
 	char fname_operlog[MAXPATHLEN];
 	char fname_userlog[MAXPATHLEN];
 	char fname_foperlog[MAXPATHLEN];
+	char fname_operspylog[MAXPATHLEN];
+	int operspy_admin_only;
 
 	MessageFile motd;
 	MessageFile opermotd;
diff -ur ircd-ratbox-1.1-2/include/s_user.h ircd-ratbox-1.1-2+opercheats/include/s_user.h
--- ircd-ratbox-1.1-2/include/s_user.h	2003-06-13 10:51:16.000000000 +0100
+++ ircd-ratbox-1.1-2+opercheats/include/s_user.h	2003-06-13 12:24:23.000000000 +0100
@@ -32,7 +32,7 @@
 struct Client;
 extern time_t LastUsedWallops;
 
-
+extern void operspy_log(struct Client *, const char *, const char *);
 extern int user_mode(struct Client *, struct Client *, int, char **);
 extern void send_umode(struct Client *, struct Client *, int, int, char *);
 extern void send_umode_out(struct Client *, struct Client *, int);
diff -ur ircd-ratbox-1.1-2/modules/core/m_mode.c ircd-ratbox-1.1-2+opercheats/modules/core/m_mode.c
--- ircd-ratbox-1.1-2/modules/core/m_mode.c	2003-06-09 21:51:34.000000000 +0100
+++ ircd-ratbox-1.1-2+opercheats/modules/core/m_mode.c	2003-06-13 12:24:23.000000000 +0100
@@ -42,6 +42,7 @@
 #include "parse.h"
 #include "modules.h"
 #include "packet.h"
+#include "sprintf_irc.h"
 
 static void m_mode(struct Client *, struct Client *, int, char **);
 
@@ -66,6 +67,43 @@
 
 const char *_version = "$Revision: 1.62 $";
 #endif
+
+static void
+loc_channel_modes(struct Channel *chptr, struct Client *client_p, char *mbuf, char *pbuf)
+{
+	int len;
+	*mbuf++ = '+';
+	*pbuf = '\0';
+
+	if(chptr->mode.mode & MODE_SECRET)
+		*mbuf++ = 's';
+	if(chptr->mode.mode & MODE_PRIVATE)
+		*mbuf++ = 'p';
+	if(chptr->mode.mode & MODE_MODERATED)
+		*mbuf++ = 'm';
+	if(chptr->mode.mode & MODE_TOPICLIMIT)
+		*mbuf++ = 't';
+	if(chptr->mode.mode & MODE_INVITEONLY)
+		*mbuf++ = 'i';
+	if(chptr->mode.mode & MODE_NOPRIVMSGS)
+		*mbuf++ = 'n';
+
+	if(chptr->mode.limit)
+	{
+		*mbuf++ = 'l';
+		len = ircsprintf(pbuf, "%d ", chptr->mode.limit);
+		pbuf += len;
+	}
+	if(*chptr->mode.key)
+	{
+		*mbuf++ = 'k';
+		ircsprintf(pbuf, "%s ", chptr->mode.key);
+	}
+
+	*mbuf++ = '\0';
+	return;
+}
+
 /*
  * m_mode - MODE command handler
  * parv[0] - sender
@@ -79,6 +117,16 @@
 	static char parabuf[MODEBUFLEN];
 	dlink_node *ptr;
 	int n = 2;
+	char *my_parv;
+	int whois_cheat = 0;
+
+	my_parv = parv[1];
+
+	if(IsOperSpy(source_p) && *my_parv == '!')
+	{
+		my_parv++;
+		whois_cheat = 1;
+	}
 
 	if(EmptyString(parv[1]))
 	{
@@ -88,21 +136,21 @@
 	}
 
 	/* Now, try to find the channel in question */
-	if(!IsChanPrefix(parv[1][0]))
+	if(!IsChanPrefix(*my_parv))
 	{
 		/* if here, it has to be a non-channel name */
 		user_mode(client_p, source_p, parc, parv);
 		return;
 	}
 
-	if(!check_channel_name(parv[1]))
+	if(!check_channel_name(my_parv))
 	{
 		sendto_one(source_p, form_str(ERR_BADCHANNAME),
 			   me.name, parv[0], (unsigned char *) parv[1]);
 		return;
 	}
 
-	chptr = hash_find_channel(parv[1]);
+	chptr = hash_find_channel(my_parv);
 
 	if(chptr == NULL)
 	{
@@ -115,7 +163,14 @@
 
 	if(parc < n + 1)
 	{
-		channel_modes(chptr, source_p, modebuf, parabuf);
+		if(whois_cheat)
+		{
+			loc_channel_modes(chptr, source_p, modebuf, parabuf);
+			operspy_log(source_p, "MODE", chptr->chname);
+		}
+		else
+			channel_modes(chptr, source_p, modebuf, parabuf);
+
 		sendto_one(source_p, form_str(RPL_CHANNELMODEIS),
 			   me.name, parv[0], parv[1], modebuf, parabuf);
 
diff -ur ircd-ratbox-1.1-2/modules/m_encap.c ircd-ratbox-1.1-2+opercheats/modules/m_encap.c
--- ircd-ratbox-1.1-2/modules/m_encap.c	2003-06-09 21:51:34.000000000 +0100
+++ ircd-ratbox-1.1-2+opercheats/modules/m_encap.c	2003-06-13 12:24:23.000000000 +0100
@@ -45,6 +45,7 @@
 #include "msg.h"
 #include "parse.h"
 #include "modules.h"
+#include "s_user.h"
 
 static void ms_encap(struct Client *client_p, struct Client *source_p,
 		     int parc, char *parv[]);
@@ -112,5 +113,37 @@
 
 	sendto_match_servs(source_p, parv[1], CAP_ENCAP,
 			   "ENCAP %s", buffer);
+
+	if(irccmp(parv[2], "OPERSPY") == 0)
+	{
+		if(parc < 4 || !IsPerson(source_p))
+			return;
+
+		if(parc < 6)
+		{
+			operspy_log(source_p, parv[3],
+				    parc < 5 ? NULL : parv[4]);
+		}
+		/* buffer all remaining into one param */
+		else
+		{
+			ptr = buffer;
+			cur_len = 0;
+
+			for(i = 4; i < parc; i++)
+			{
+				len = strlen(parv[i]) + 1;
+
+				if((size_t)(cur_len + len) >= sizeof(buffer))
+					return;
+
+				snprintf(ptr, sizeof(buffer) - cur_len, "%s ",
+					 parv[i]);
+				ptr += len;
+				cur_len += len;
+			}
+			operspy_log(source_p, parv[3], buffer);
+		}
+	}		    
 }
 
diff -ur ircd-ratbox-1.1-2/modules/m_who.c ircd-ratbox-1.1-2+opercheats/modules/m_who.c
--- ircd-ratbox-1.1-2/modules/m_who.c	2003-06-09 21:51:34.000000000 +0100
+++ ircd-ratbox-1.1-2+opercheats/modules/m_who.c	2003-06-13 12:24:23.000000000 +0100
@@ -42,6 +42,7 @@
 #include "parse.h"
 #include "modules.h"
 #include "packet.h"
+#include "s_user.h"
 
 static void m_who(struct Client *, struct Client *, int, char **);
 
@@ -67,7 +68,7 @@
 static void do_who_on_channel(struct Client *source_p,
 			      struct Channel *chptr, const char *real_name, int server_oper, int member);
 
-static void who_global(struct Client *source_p, char *mask, int server_oper);
+static void who_global(struct Client *source_p, char *mask, int server_oper, int);
 
 static void do_who(struct Client *source_p, struct Client *target_p, const char *chname, const char *op_flags);
 
@@ -88,6 +89,7 @@
 	struct Channel *mychannel = NULL;
 	int server_oper = parc > 2 ? (*parv[2] == 'o') : 0;	/* Show OPERS only */
 	int member;
+	int whois_cheat = 0;
 
 	/* See if mask is there, collapse it or return if not there */
 
@@ -106,7 +108,7 @@
 		if(!IsFloodDone(source_p))
 			flood_endgrace(source_p);
 
-		who_global(source_p, mask, server_oper);
+		who_global(source_p, mask, server_oper, 0);
 		sendto_one(source_p, form_str(RPL_ENDOFWHO), me.name, parv[0], "*");
 		return;
 	}
@@ -133,6 +135,12 @@
 		return;
 	}
 
+	if(IsOperSpy(source_p) && *mask == '!')
+	{
+		mask++;
+		whois_cheat = 1;
+	}
+
 	/* '/who #some_channel' */
 
 	if(IsChannelName(mask))
@@ -143,7 +151,10 @@
 		chptr = hash_find_channel(mask);
 		if(chptr != NULL)
 		{
-			if(IsMember(source_p, chptr))
+			if(whois_cheat)
+				operspy_log(source_p, "WHO", chptr->chname);
+
+			if(IsMember(source_p, chptr) || whois_cheat)
 				do_who_on_channel(source_p, chptr, chptr->chname, server_oper, YES);
 			else if(!SecretChannel(chptr))
 				do_who_on_channel(source_p, chptr, chptr->chname, server_oper, NO);
@@ -203,9 +214,9 @@
 
 	/* '/who 0' */
 	if((*(mask + 1) == '\0') && (*mask == '0'))
-		who_global(source_p, NULL, server_oper);
+		who_global(source_p, NULL, server_oper, 0);
 	else
-		who_global(source_p, mask, server_oper);
+		who_global(source_p, mask, server_oper, whois_cheat);
 
 	/* Wasn't a nick, wasn't a channel, wasn't a '*' so ... */
 	sendto_one(source_p, form_str(RPL_ENDOFWHO), me.name, parv[0], mask);
@@ -274,7 +285,7 @@
  */
 
 static void
-who_global(struct Client *source_p, char *mask, int server_oper)
+who_global(struct Client *source_p, char *mask, int server_oper, int whois_cheat)
 {
 	struct Channel *chptr = NULL;
 	struct Client *target_p;
@@ -283,13 +294,19 @@
 
 	/* first, list all matching INvisible clients on common channels */
 
-	DLINK_FOREACH(lp, source_p->user->channel.head)
+	if(whois_cheat)
+		operspy_log(source_p, "WHO", mask);
+
+	if(!whois_cheat)
 	{
-		chptr = lp->data;
-		who_common_channel(source_p, chptr->chanops, mask, server_oper, &maxmatches);
-		who_common_channel(source_p, chptr->chanops_voiced, mask, server_oper, &maxmatches);
-		who_common_channel(source_p, chptr->voiced, mask, server_oper, &maxmatches);
-		who_common_channel(source_p, chptr->peons, mask, server_oper, &maxmatches);
+		DLINK_FOREACH(lp, source_p->user->channel.head)
+		{
+			chptr = lp->data;
+			who_common_channel(source_p, chptr->chanops, mask, server_oper, &maxmatches);
+			who_common_channel(source_p, chptr->chanops_voiced, mask, server_oper, &maxmatches);
+			who_common_channel(source_p, chptr->voiced, mask, server_oper, &maxmatches);
+			who_common_channel(source_p, chptr->peons, mask, server_oper, &maxmatches);
+		}
 	}
 
 	/* second, list all matching visible clients */
@@ -299,7 +316,7 @@
 		if(!IsPerson(target_p))
 			continue;
 
-		if(IsInvisible(target_p))
+		if(IsInvisible(target_p) && !whois_cheat)
 		{
 			ClearMark(target_p);
 			continue;
diff -ur ircd-ratbox-1.1-2/modules/m_whois.c ircd-ratbox-1.1-2+opercheats/modules/m_whois.c
--- ircd-ratbox-1.1-2/modules/m_whois.c	2003-06-09 21:51:34.000000000 +0100
+++ ircd-ratbox-1.1-2+opercheats/modules/m_whois.c	2003-06-13 12:24:23.000000000 +0100
@@ -45,10 +45,11 @@
 #include "parse.h"
 #include "modules.h"
 #include "hook.h"
+#include "s_user.h"
 
 static int do_whois(struct Client *client_p, struct Client *source_p, int parc, char *parv[]);
-static int single_whois(struct Client *source_p, struct Client *target_p, int wilds, int glob);
-static void whois_person(struct Client *source_p, struct Client *target_p, int glob);
+static int single_whois(struct Client *source_p, struct Client *target_p, int wilds, int glob, int);
+static void whois_person(struct Client *source_p, struct Client *target_p, int glob, int);
 static int global_whois(struct Client *source_p, char *nick, int wilds, int glob);
 
 static void m_whois(struct Client *, struct Client *, int, char **);
@@ -165,6 +166,7 @@
 	int found = NO;
 	int wilds;
 	int glob = 0;
+	int whois_cheat = 0;
 
 	/* This lets us make all "whois nick" queries look the same, and all
 	 * "whois nick nick" queries look the same.  We have to pass it all
@@ -180,6 +182,12 @@
 	(void) collapse(nick);
 	wilds = (strchr(nick, '?') || strchr(nick, '*'));
 
+	if(IsOperSpy(source_p) && *nick == '!')
+	{
+		whois_cheat = 1;
+		nick++;
+	}
+
 	if(!wilds)
 	{
 		if((target_p = find_client(nick)) != NULL)
@@ -193,7 +201,18 @@
 
 			if(IsPerson(target_p))
 			{
-				(void) single_whois(source_p, target_p, wilds, glob);
+				if(whois_cheat)
+				{
+					char buffer[BUFSIZE];
+
+					snprintf(buffer, sizeof(buffer), "%s!%s@%s %s",
+						 target_p->name, target_p->username,
+						 target_p->host, target_p->user->server);
+
+					operspy_log(source_p, "WHOIS", buffer);
+				}
+
+				(void) single_whois(source_p, target_p, wilds, glob, whois_cheat);
 				found = YES;
 			}
 		}
@@ -242,8 +261,7 @@
 		if(found >= 50)
 			return found;
 
-		if(IsServer(target_p) || IsInvisible(target_p) ||
-		   !IsRegistered(target_p))
+		if(IsServer(target_p) || !IsRegistered(target_p))
 			continue;
 		/*
 		 * 'Rules' established for sending a WHOIS reply:
@@ -258,7 +276,7 @@
 		 *   the target user(s) are on;
 		 */
 
-		if(single_whois(source_p, target_p, wilds, glob))
+		if(single_whois(source_p, target_p, wilds, glob, 0))
 			found++;
 	}
 
@@ -276,7 +294,8 @@
  * 		  writing results to source_p
  */
 static int
-single_whois(struct Client *source_p, struct Client *target_p, int wilds, int glob)
+single_whois(struct Client *source_p, struct Client *target_p, int wilds, int glob,
+		int whois_cheat)
 {
 	dlink_node *ptr;
 	struct Channel *chptr;
@@ -323,7 +342,7 @@
 	}
 
 	if(showperson)
-		whois_person(source_p, target_p, glob);
+		whois_person(source_p, target_p, glob, whois_cheat);
 
 	return showperson;
 }
@@ -337,7 +356,8 @@
  * Side Effects	- 
  */
 static void
-whois_person(struct Client *source_p, struct Client *target_p, int glob)
+whois_person(struct Client *source_p, struct Client *target_p, int glob,
+		int whois_cheat)
 {
 	char buf[BUFSIZE];
 	char *chname;
@@ -351,6 +371,7 @@
 	int tlen;
 	int reply_to_send = NO;
 	struct hook_mfunc_data hd;
+	int whois_len = 4;
 
 	a2client_p = find_server(target_p->user->server);
 
@@ -365,15 +386,18 @@
 	cur_len = mlen;
 	t = buf + mlen;
 
+	if(whois_cheat)
+	  whois_len = 5;
+
 	DLINK_FOREACH(lp, target_p->user->channel.head)
 	{
 		chptr = lp->data;
 		chname = chptr->chname;
 
-		if(ShowChannel(source_p, chptr))
+		if(ShowChannel(source_p, chptr) || whois_cheat)
 		{
 
-			if((cur_len + strlen(chname) + 2) > (BUFSIZE - 4))
+			if((cur_len + strlen(chname) + 2) > (BUFSIZE - whois_len))
 			{
 				sendto_one(source_p, "%s", buf);
 				cur_len = mlen;
@@ -386,7 +410,9 @@
 			}
 			else
 			{
-				ircsprintf(t, "%s%s ", channel_chanop_or_voice(chptr, target_p),
+				ircsprintf(t, "%s%s%s ", 
+				    	   ShowChannel(source_p, chptr) ? "" : "!",
+				    	   channel_chanop_or_voice(chptr, target_p),
 					   chname);
 			}
 
diff -ur ircd-ratbox-1.1-2/src/newconf.c ircd-ratbox-1.1-2+opercheats/src/newconf.c
--- ircd-ratbox-1.1-2/src/newconf.c	2003-06-09 21:51:34.000000000 +0100
+++ ircd-ratbox-1.1-2+opercheats/src/newconf.c	2003-06-13 12:24:23.000000000 +0100
@@ -330,6 +330,7 @@
 	add_conf_item("logging", "fname_userlog", CF_QSTRING, conf_set_logging_fname_userlog);
 	add_conf_item("logging", "fname_operlog", CF_QSTRING, conf_set_logging_fname_operlog);
 	add_conf_item("logging", "fname_foperlog", CF_QSTRING, conf_set_logging_fname_foperlog);
+	add_conf_item("logging", "fname_operspylog", CF_QSTRING, conf_set_logging_fname_operspylog);
 
 	add_top_conf("operator", conf_begin_oper, conf_end_oper);
 	add_conf_item("operator", "name", CF_QSTRING, conf_set_oper_name);
@@ -348,6 +349,7 @@
 	add_conf_item("operator", "rehash", CF_YESNO, conf_set_oper_rehash);
 	add_conf_item("operator", "admin", CF_YESNO, conf_set_oper_admin);
 	add_conf_item("operator", "hidden_admin", CF_YESNO, conf_set_oper_hidden_admin);
+	add_conf_item("operator", "oper_spy", CF_YESNO, conf_set_oper_operspy);
 	add_conf_item("operator", "encrypted", CF_YESNO, conf_set_oper_encrypted);
 	add_conf_item("operator", "rsa_public_key_file", CF_QSTRING,
 		      conf_set_oper_rsa_public_key_file);
@@ -441,6 +443,8 @@
 	add_conf_item("cluster", "type", CF_STRING | CF_FLIST, conf_set_cluster_type);
 
 	add_top_conf("general", NULL, NULL);
+	add_conf_item("general", "operspy_admin_only", CF_YESNO,
+		      conf_set_general_operspy_admin_only);
 	add_conf_item("general", "failed_oper_notice", CF_YESNO,
 		      conf_set_general_failed_oper_notice);
 	add_conf_item("general", "anti_nick_flood", CF_YESNO, conf_set_general_anti_nick_flood);
@@ -778,6 +782,12 @@
 	strlcpy(ConfigFileEntry.fname_operlog, data, sizeof(ConfigFileEntry.fname_operlog));
 }
 
+void
+conf_set_logging_fname_operspylog(void *data)
+{
+	strlcpy(ConfigFileEntry.fname_operspylog, data, sizeof(ConfigFileEntry.fname_operspylog));
+}
+
 static struct
 {
 	const char *name;
@@ -1296,6 +1306,17 @@
 		yy_achead->port &= ~OPER_HIDDENADMIN;
 }
 
+void
+conf_set_oper_operspy(void *data)
+{
+	int yesno = *(int *) data;
+
+	if(yesno)
+		yy_achead->port |= OPER_SPY;
+	else
+		yy_achead->port &= ~OPER_SPY;
+}
+
 int
 conf_begin_class(struct TopConf *tc)
 {
@@ -2448,6 +2469,11 @@
 }
 
 void
+conf_set_general_operspy_admin_only(void *data)
+{
+	ConfigFileEntry.operspy_admin_only = *(unsigned int *) data;
+}
+void
 conf_set_general_failed_oper_notice(void *data)
 {
 	ConfigFileEntry.failed_oper_notice = *(unsigned int *) data;
diff -ur ircd-ratbox-1.1-2/src/s_conf.c ircd-ratbox-1.1-2+opercheats/src/s_conf.c
--- ircd-ratbox-1.1-2/src/s_conf.c	2003-06-09 21:51:34.000000000 +0100
+++ ircd-ratbox-1.1-2+opercheats/src/s_conf.c	2003-06-13 12:24:23.000000000 +0100
@@ -1123,6 +1123,7 @@
 	ConfigFileEntry.fname_userlog[0] = '\0';
 	ConfigFileEntry.fname_foperlog[0] = '\0';
 	ConfigFileEntry.fname_operlog[0] = '\0';
+	ConfigFileEntry.fname_operspylog[0] = '\0';
 	ConfigFileEntry.glines = NO;
 	ConfigFileEntry.use_egd = NO;
 	/* don't reset msglocale setting -- we'd overwrite then env string */
@@ -1151,7 +1152,7 @@
 
 	ConfigFileEntry.oper_umodes = UMODE_LOCOPS | UMODE_SERVNOTICE |
 		UMODE_OPERWALL | UMODE_WALLOP;
-	ConfigFileEntry.oper_only_umodes = UMODE_DEBUG;
+	ConfigFileEntry.oper_only_umodes = UMODE_DEBUG | UMODE_OPERSPY;
 
 	ConfigChannel.use_except = YES;
 	ConfigChannel.use_invex = YES;
@@ -1624,7 +1625,7 @@
 oper_flags_as_string(int flags)
 {
 	/* This MUST be extended if we add any more modes... -Hwy */
-	static char flags_out[18];
+	static char flags_out[20];
 	char *flags_ptr;
 
 	flags_ptr = flags_out;
@@ -1662,6 +1663,8 @@
 		*flags_ptr++ = 'l';
 	if(flags & UMODE_CALLERID)
 		*flags_ptr++ = 'g';
+	if(flags & UMODE_OPERSPY)
+		*flags_ptr++ = 'Z';
 	*flags_ptr = '\0';
 
 	return (flags_out);
diff -ur ircd-ratbox-1.1-2/src/s_user.c ircd-ratbox-1.1-2+opercheats/src/s_user.c
--- ircd-ratbox-1.1-2/src/s_user.c	2003-06-09 21:51:34.000000000 +0100
+++ ircd-ratbox-1.1-2+opercheats/src/s_user.c	2003-06-14 10:44:14.000000000 +0100
@@ -93,6 +93,7 @@
 	{UMODE_EXTERNAL, 'x'},
 	{UMODE_SPY, 'y'},
 	{UMODE_OPERWALL, 'z'},
+	{UMODE_OPERSPY,	'Z'},
 	{0, 0}
 };
 
@@ -133,7 +134,7 @@
 	0,			/* W */
 	0,			/* X */
 	0,			/* Y */
-	0,			/* Z 0x5A */
+	UMODE_OPERSPY,			/* Z 0x5A */
 	0, 0, 0, 0, 0,		/* 0x5F */
 	/* 0x60 */ 0,
 	UMODE_ADMIN,		/* a */
@@ -182,6 +183,44 @@
 									/* 0xFF */
 };
 
+void
+operspy_log(struct Client *source_p, const char *token, const char *arg)
+{
+	FBFILE *operspy_fb;
+	char linebuf[BUFSIZE];
+
+	/* otherwise its propagated already */
+	if(MyClient(source_p))
+		sendto_match_servs(source_p, "*", CAP_ENCAP,
+				   "ENCAP * OPERSPY %s %s",
+				   token, arg ? arg : "");
+
+	sendto_realops_flags(UMODE_OPERSPY,
+			     ConfigFileEntry.operspy_admin_only ? L_ADMIN : L_ALL,
+			     "OPERSPY %s %s %s",
+			     get_oper_name(source_p), token,
+			     arg ? arg : "");
+
+	if(ConfigFileEntry.fname_operspylog[0] == '\0')
+		return;
+
+	if((operspy_fb = fbopen(ConfigFileEntry.fname_operspylog, "r")) != NULL)
+	{
+		fbclose(operspy_fb);
+		operspy_fb = fbopen(ConfigFileEntry.fname_operspylog, "a");
+	}
+
+	if(operspy_fb != NULL)
+	{
+		snprintf(linebuf, sizeof(linebuf),
+			 "OPERSPY %s %s %s\n",
+			 get_oper_name(source_p), token,
+			 arg ? arg : "");
+		fbputs(linebuf, operspy_fb);
+		fbclose(operspy_fb);
+	}
+}
+
 /*
  * show_lusers -
  *
