diff --git a/src/sbbs3/umonitor/spyon.c b/src/sbbs3/umonitor/spyon.c
index 4d26115e6ecf1668b63e703d17e96b3b939c2ee0..54108c04e26611d42cb459b26395d267c46a5d47 100644
--- a/src/sbbs3/umonitor/spyon.c
+++ b/src/sbbs3/umonitor/spyon.c
@@ -29,15 +29,44 @@
 
 #include <genwrap.h>
 #include <sockwrap.h>
+#include "ini_file.h"
 #include "spyon.h"
 #include "ciolib.h"
 #include "cterm.h"
 #include "uifc.h"
+#include "str_util.h"
 
 struct cterminal *cterm;
 extern uifcapi_t uifc; /* User Interface (UIFC) Library API */
+cterm_emulation_t cterm_emu = CTERM_EMULATION_ANSI_BBS;
+char term_type[INI_MAX_VALUE_LEN] = "unknown";
+int term_cols = 80;
+int term_rows = 25;
+bool term_utf8 = false;
 
-int spyon(char *sockname)  {
+time_t read_term_ini(const char* path)
+{
+	FILE* fp = iniOpenFile(path, /* for_modify: */false);
+	if(fp != NULL) {
+		char chars[INI_MAX_VALUE_LEN];
+		iniReadString(fp, ROOT_SECTION, "type", /* default: */NULL, term_type);
+		iniReadString(fp, ROOT_SECTION, "chars", /* default: */NULL, chars);
+		term_cols = iniReadInteger(fp, ROOT_SECTION, "cols", term_cols);
+		term_rows = iniReadInteger(fp, ROOT_SECTION, "rows", term_rows);
+		term_utf8 = false;
+		if(stricmp(term_type, "PETSCII") == 0)
+			cterm_emu = CTERM_EMULATION_PETASCII;
+		else {
+			cterm_emu = CTERM_EMULATION_ANSI_BBS;
+			if(stricmp(chars, "UTF-8") == 0)
+				term_utf8 = true;
+		}
+		fclose(fp);
+	}
+	return fdate(path);
+}
+
+int spyon(char *sockname, int nodenum, scfg_t* cfg)  {
 #if defined _WIN32
 	uifc.msg("Spying not supported on Win32 yet!");
 	return SPY_SOCKETLOST;
@@ -46,12 +75,14 @@ int spyon(char *sockname)  {
 	struct sockaddr_un spy_name;
 	socklen_t	spy_len;
 	unsigned char		key;
-	unsigned char		buf;
+	char	buf[100000];
+	char	term_ini_fname[MAX_PATH + 1];
+	time_t	term_ini_ftime;
+	int		idle_count = 0;
 	int		i;
 	fd_set	rd;
 	bool	b;
 	int		retval=0;
-	int		telnet_strip=0;
 	struct text_info ti;
 	char *scrn;
 
@@ -63,6 +94,11 @@ int spyon(char *sockname)  {
 		return(SPY_NOSOCKET);
 	}
 	
+	snprintf(term_ini_fname, sizeof term_ini_fname, "%sterminal.ini"
+		,cfg->node_path[nodenum - 1]);
+
+	term_ini_ftime = read_term_ini(term_ini_fname);
+
 	spy_name.sun_family=AF_UNIX;
 	SAFECOPY(spy_name.sun_path,sockname);
 #ifdef SUN_LEN
@@ -82,9 +118,9 @@ int spyon(char *sockname)  {
 	textbackground(BLUE);
 	clrscr();
 	gotoxy(1,ti.screenheight);
-	cputs("Local spy mode... press CTRL-C to return to monitor");
+	cprintf("Spying on node %d ... press CTRL-C to return to monitor", nodenum);
 	clreol();
-	cterm = cterm_init(ti.screenheight - 1, ti.screenwidth, 1, 1, 0, 0, NULL, CTERM_EMULATION_ANSI_BBS);
+	cterm = cterm_init(ti.screenheight - 1, ti.screenwidth, 1, 1, 0, 0, NULL, cterm_emu);
 	while(spy_sock!=INVALID_SOCKET && cterm != NULL)  {
 		struct timeval tv;
 		tv.tv_sec=0;
@@ -104,21 +140,21 @@ int spyon(char *sockname)  {
 			break;
 		}
 		if(spy_sock != INVALID_SOCKET && FD_ISSET(spy_sock,&rd))  {
-			if((i=read(spy_sock,&buf,1))==1)  {
-				if(telnet_strip) {
-					telnet_strip++;
-					if(buf==255 && telnet_strip==2) {
-						telnet_strip=0;
-						cterm_write(cterm, &buf,1,NULL,0,NULL);
+			if((i=read(spy_sock, buf, sizeof(buf) - 1)) > 0)  {
+				if(idle_count >= 1000 && fdate(term_ini_fname) > term_ini_ftime) {
+					term_ini_ftime = read_term_ini(term_ini_fname);
+					if(cterm_emu != cterm->emulation) {
+						cterm_end(cterm, 1);
+						cterm = cterm_init(ti.screenheight - 1, ti.screenwidth, 1, 1, 0, 0, NULL, cterm_emu);
 					}
-					if(telnet_strip==3)
-						telnet_strip=0;
 				}
-				else
-					if(buf==255)
-						telnet_strip=1;
-					else
-						cterm_write(cterm, &buf,1,NULL,0,NULL);
+				if(term_utf8) {
+					buf[i] = '\0';
+					utf8_to_cp437_inplace(buf);
+					i = strlen(buf);
+				}
+				idle_count = 0;
+				cterm_write(cterm, buf, i, NULL, 0, NULL);
 			}
 			else if(i<0) {
 				close(spy_sock);
@@ -126,6 +162,8 @@ int spyon(char *sockname)  {
 				retval=SPY_SOCKETLOST;
 				break;
 			}
+		} else {
+			++idle_count;
 		}
 		if(kbhit())  {
 			key=getch();
diff --git a/src/sbbs3/umonitor/spyon.h b/src/sbbs3/umonitor/spyon.h
index ff55dea710cf18f4dce6d846ed23228750fa1ee5..13d88dfd0309141fcaa0cd2cd40f65fc959f6676 100644
--- a/src/sbbs3/umonitor/spyon.h
+++ b/src/sbbs3/umonitor/spyon.h
@@ -1,9 +1,5 @@
-/* spyon.h */
-
 /* Synchronet for *nix node spy headers */
 
-/* $Id: spyon.h,v 1.3 2018/07/24 01:12:32 rswindell Exp $ */
-
 /****************************************************************************
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
@@ -17,24 +13,14 @@
  * See the GNU General Public License for more details: gpl.txt or			*
  * http://www.fsf.org/copyleft/gpl.html										*
  *																			*
- * Anonymous FTP access to the most recent released source is available at	*
- * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
- *																			*
- * Anonymous CVS access to the development source and modification history	*
- * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
- * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
- *     (just hit return, no password is necessary)							*
- * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
- *																			*
  * For Synchronet coding style and modification guidelines, see				*
  * http://www.synchro.net/source.html										*
  *																			*
- * You are encouraged to submit any modifications (preferably in Unix diff	*
- * format) via e-mail to mods@synchro.net									*
- *																			*
  * Note: If this box doesn't appear square, then you need to fix your tabs.	*
  ****************************************************************************/
 
+#include "scfgdefs.h"
+
 enum {
 	 SPY_NOSOCKET
 	,SPY_NOCONNECT
@@ -44,4 +30,4 @@ enum {
 	,SPY_CLOSED
 	};
 
-int spyon(char *sockname);
+int spyon(char *sockname, int nodenum, scfg_t*);
diff --git a/src/sbbs3/umonitor/umonitor.c b/src/sbbs3/umonitor/umonitor.c
index 1f1bf1f35ef7581404cb8036f81e23ed63a23ae6..c54b7fb5774cd479e777757f398591bc43da851a 100644
--- a/src/sbbs3/umonitor/umonitor.c
+++ b/src/sbbs3/umonitor/umonitor.c
@@ -161,7 +161,7 @@ void node_toggles(scfg_t *cfg,int nodenum)  {
 	}
 }
 
-int dospy(int nodenum, bbs_startup_t *bbs_startup)  {
+int dospy(scfg_t *cfg, int nodenum, bbs_startup_t *bbs_startup)  {
 	char str[80],str2[80];
 	int i;
 
@@ -169,7 +169,7 @@ int dospy(int nodenum, bbs_startup_t *bbs_startup)  {
 		snprintf(str,sizeof(str),"%slocalspy%d.sock", bbs_startup->temp_dir, nodenum);
 	else
 		snprintf(str,sizeof(str),"%slocalspy%d.sock", bbs_startup->ctrl_dir, nodenum);
-	i=spyon(str);
+	i=spyon(str, nodenum, cfg);
 	switch(i) {
 		case SPY_NOSOCKET:
 			uifc.msg("Could not create socket");
@@ -1208,7 +1208,7 @@ USAGE:
 		}
 
 		if(j==-2-CIO_KEY_F(12)) {	/* Spy */
-			dospy(main_dflt,&bbs_startup);
+			dospy(&cfg,main_dflt,&bbs_startup);
 			continue;
 		}
 
@@ -1297,7 +1297,7 @@ USAGE:
 							break;
 
 						case 1:	/* Spy */
-							dospy(j,&bbs_startup);
+							dospy(&cfg,j,&bbs_startup);
 							break;
 
 						case 2:	/* Send message */
@@ -1366,7 +1366,7 @@ USAGE:
 					switch(uifc.list(WIN_MID|WIN_SAV|WIN_ACT,0,0,0,&i,0,"Node Options",opt))  {
 
 						case 0:	/* Spy */
-							dospy(j,&bbs_startup);
+							dospy(&cfg,j,&bbs_startup);
 							break;
 
 						case 1: /* Chat with User */